event.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /* MegaZeux
  2. *
  3. * Copyright (C) 2016 Adrian Siekierka <asiekierka@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. #include "../../src/event.h"
  20. #include "../../src/graphics.h"
  21. #include "../../src/platform.h"
  22. #include "../../src/util.h"
  23. #include <3ds.h>
  24. #include "event.h"
  25. #include "keyboard.h"
  26. extern struct input_status input;
  27. static enum bottom_screen_mode b_mode;
  28. static enum focus_mode allow_focus_changes = FOCUS_ALLOW;
  29. static boolean is_dragging = false;
  30. boolean update_hid(void);
  31. enum focus_mode get_allow_focus_changes(void)
  32. {
  33. return allow_focus_changes;
  34. }
  35. enum bottom_screen_mode get_bottom_screen_mode(void)
  36. {
  37. return b_mode;
  38. }
  39. boolean __update_event_status(void)
  40. {
  41. boolean retval = false;
  42. retval |= aptMainLoop();
  43. retval |= update_hid();
  44. return retval;
  45. }
  46. void __wait_event(void)
  47. {
  48. while(!__update_event_status())
  49. gspWaitForVBlank();
  50. }
  51. // Convert the 3DS axis ranges to the MZX axis ranges. The 3DS uses values in
  52. // (roughly) the -150 to 150 range, but MZX uses the full range of a Sint16.
  53. // The 3DS Y axis is also inverted from the typical axis direction, but that
  54. // is fixed in check_circle below.
  55. static inline Sint16 axis_convert(s16 value)
  56. {
  57. int new_value = ((int)value) * 32768 / 150;
  58. return (Sint16)CLAMP(new_value, -32768, 32767);
  59. }
  60. static inline boolean check_circle(struct buffered_status *status,
  61. circlePosition *current, circlePosition *prev, Uint32 axis_x, Uint32 axis_y)
  62. {
  63. boolean rval = false;
  64. if(current->dx != prev->dx)
  65. {
  66. joystick_axis_update(status, 0, axis_x, axis_convert(current->dx));
  67. rval = true;
  68. }
  69. if(current->dy != prev->dy)
  70. {
  71. // 3DS has an inverted Y axis on the circle pad vs. most controllers.
  72. joystick_axis_update(status, 0, axis_y, axis_convert(-current->dy));
  73. rval = true;
  74. }
  75. return rval;
  76. }
  77. static inline boolean check_hat(struct buffered_status *status,
  78. Uint32 down, Uint32 up, Uint32 key, enum joystick_hat dir)
  79. {
  80. if(down & key)
  81. {
  82. joystick_hat_update(status, 0, dir, true);
  83. return true;
  84. }
  85. else
  86. if(up & key)
  87. {
  88. joystick_hat_update(status, 0, dir, false);
  89. return true;
  90. }
  91. return false;
  92. }
  93. static inline boolean check_joy(struct buffered_status *status,
  94. Uint32 down, Uint32 up, Uint32 key, Uint32 button)
  95. {
  96. if(down & key)
  97. {
  98. joystick_button_press(status, 0, button);
  99. return true;
  100. }
  101. else
  102. if(up & key)
  103. {
  104. joystick_button_release(status, 0, button);
  105. return true;
  106. }
  107. return false;
  108. }
  109. static inline boolean ctr_is_mouse_area(touchPosition *touch)
  110. {
  111. int mx, my;
  112. if(b_mode == BOTTOM_SCREEN_MODE_KEYBOARD)
  113. {
  114. mx = touch->px * 4 - 320;
  115. my = touch->py * 4 - (13 * 4);
  116. if(mx < 0 || mx >= 640 || my < 0 || my >= 350)
  117. return false;
  118. else
  119. return true;
  120. }
  121. else
  122. {
  123. return true;
  124. }
  125. }
  126. static inline boolean ctr_update_touch(struct buffered_status *status,
  127. touchPosition *touch)
  128. {
  129. int mx, my;
  130. if(b_mode == BOTTOM_SCREEN_MODE_KEYBOARD)
  131. {
  132. mx = touch->px * 4 - 320;
  133. my = touch->py * 4 - (13 * 4);
  134. if(mx < 0 || mx >= 640 || my < 0 || my >= 350)
  135. return false;
  136. }
  137. else
  138. {
  139. mx = touch->px * 2;
  140. my = touch->py * 2 - 64;
  141. if(mx < 0) mx = 0;
  142. if(mx >= 640) mx = 639;
  143. if(my < 0) my = 0;
  144. if(my >= 350) my = 349;
  145. }
  146. if((Uint32) mx != status->real_mouse_x || (Uint32) my != status->real_mouse_y)
  147. {
  148. status->real_mouse_x = mx;
  149. status->real_mouse_y = my;
  150. status->mouse_x = mx / 8;
  151. status->mouse_y = my / 14;
  152. status->mouse_moved = true;
  153. allow_focus_changes = FOCUS_PASS;
  154. focus_pixel(mx, my);
  155. allow_focus_changes = FOCUS_FORBID;
  156. return true;
  157. }
  158. else
  159. {
  160. return false;
  161. }
  162. }
  163. static inline boolean ctr_update_cstick(struct buffered_status *status)
  164. {
  165. circlePosition pos;
  166. int dmx, dmy, nmx, nmy;
  167. hidCstickRead(&pos);
  168. dmx = pos.dx / 3;
  169. dmy = pos.dy / 3;
  170. if(dmx != 0 || dmy != 0)
  171. {
  172. nmx = status->real_mouse_x + dmx;
  173. nmy = status->real_mouse_y + dmy;
  174. if(nmx < 0) nmx = 0;
  175. if(nmx >= 640) nmx = 639;
  176. if(nmy < 0) nmy = 0;
  177. if(nmy >= 350) nmy = 349;
  178. if((Uint32) nmx != status->real_mouse_x ||
  179. (Uint32) nmy != status->real_mouse_y)
  180. {
  181. status->real_mouse_x = nmx;
  182. status->real_mouse_y = nmy;
  183. status->mouse_x = nmx / 8;
  184. status->mouse_y = nmy / 14;
  185. status->mouse_moved = true;
  186. focus_pixel(nmx, nmy);
  187. return true;
  188. }
  189. }
  190. return false;
  191. }
  192. boolean update_hid(void)
  193. {
  194. struct buffered_status *status = store_status();
  195. Uint32 down, held, up;
  196. boolean retval = false;
  197. touchPosition touch;
  198. circlePosition cpad;
  199. static circlePosition last_cpad;
  200. hidScanInput();
  201. hidCircleRead(&cpad);
  202. down = hidKeysDown();
  203. held = hidKeysHeld();
  204. up = hidKeysUp();
  205. retval |= check_circle(status, &cpad, &last_cpad, 0, 1);
  206. retval |= check_hat(status, down, up, KEY_DUP, JOYHAT_UP);
  207. retval |= check_hat(status, down, up, KEY_DDOWN, JOYHAT_DOWN);
  208. retval |= check_hat(status, down, up, KEY_DLEFT, JOYHAT_LEFT);
  209. retval |= check_hat(status, down, up, KEY_DRIGHT, JOYHAT_RIGHT);
  210. retval |= check_joy(status, down, up, KEY_A, 0);
  211. retval |= check_joy(status, down, up, KEY_B, 1);
  212. retval |= check_joy(status, down, up, KEY_X, 2);
  213. retval |= check_joy(status, down, up, KEY_Y, 3);
  214. retval |= check_joy(status, down, up, KEY_L, 4);
  215. retval |= check_joy(status, down, up, KEY_SELECT, 6);
  216. retval |= check_joy(status, down, up, KEY_START, 7);
  217. retval |= check_joy(status, down, up, KEY_ZL, 8);
  218. retval |= check_joy(status, down, up, KEY_ZR, 9);
  219. last_cpad = cpad;
  220. if(down & KEY_R)
  221. {
  222. b_mode = (b_mode + 1) % BOTTOM_SCREEN_MODE_MAX;
  223. retval = true;
  224. }
  225. if((down | held | up) & KEY_TOUCH)
  226. {
  227. hidTouchRead(&touch);
  228. if((down & KEY_TOUCH) && ctr_is_mouse_area(&touch))
  229. {
  230. status->mouse_button = MOUSE_BUTTON_LEFT;
  231. status->mouse_repeat = MOUSE_BUTTON_LEFT;
  232. status->mouse_button_state |= MOUSE_BUTTON(MOUSE_BUTTON_LEFT);
  233. status->mouse_repeat_state = 1;
  234. status->mouse_drag_state = -1;
  235. status->mouse_time = get_ticks();
  236. is_dragging = true;
  237. allow_focus_changes = FOCUS_FORBID;
  238. retval = true;
  239. }
  240. if(is_dragging)
  241. {
  242. if(up & KEY_TOUCH)
  243. {
  244. status->mouse_button_state &= ~MOUSE_BUTTON(MOUSE_BUTTON_LEFT);
  245. status->mouse_repeat = 0;
  246. status->mouse_repeat_state = 0;
  247. status->mouse_drag_state = -0;
  248. allow_focus_changes = FOCUS_ALLOW;
  249. is_dragging = false;
  250. retval = true;
  251. }
  252. else
  253. {
  254. retval |= ctr_update_touch(status, &touch);
  255. }
  256. }
  257. retval |= ctr_keyboard_update(status);
  258. }
  259. // retval |= ctr_update_cstick(status);
  260. return retval;
  261. }