in_psp.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * (C) Gražvydas "notaz" Ignotas, 2006-2012
  3. * (C) kub 2020
  4. *
  5. * This work is licensed under the terms of any of these licenses
  6. * (at your option):
  7. * - GNU GPL, version 2 or later.
  8. * - GNU LGPL, version 2.1 or later.
  9. * - MAME license.
  10. * See the COPYING file in the top-level directory.
  11. */
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <fcntl.h>
  18. #include <unistd.h>
  19. #include "../libpicofe/input.h"
  20. #include "psp.h"
  21. #include "in_psp.h"
  22. #define IN_PSP_PREFIX "psp:"
  23. #define IN_PSP_NBUTTONS 32
  24. /* note: in_psp handles combos (if 2 btns have the same bind,
  25. * both must be pressed for action to happen) */
  26. static int in_psp_combo_keys = 0;
  27. static int in_psp_combo_acts = 0;
  28. static const char *in_psp_keys[IN_PSP_NBUTTONS] = {
  29. [0 ... IN_PSP_NBUTTONS-1] = NULL,
  30. };
  31. /* credits to https://graphics.stanford.edu/~seander/bithacks.html */
  32. static int lg2(unsigned v)
  33. {
  34. int r, s;
  35. r = (v > 0xFFFF) << 4; v >>= r;
  36. s = (v > 0xFF ) << 3; v >>= s; r |= s;
  37. s = (v > 0xF ) << 2; v >>= s; r |= s;
  38. s = (v > 0x3 ) << 1; v >>= s; r |= s;
  39. r |= (v >> 1);
  40. return r;
  41. }
  42. static int in_psp_get_bits(void)
  43. {
  44. return psp_pad_read(0);
  45. }
  46. static void in_psp_probe(const in_drv_t *drv)
  47. {
  48. in_register(IN_PSP_PREFIX "PSP pad", -1, NULL,
  49. IN_PSP_NBUTTONS, in_psp_keys, 1);
  50. }
  51. static void in_psp_free(void *drv_data)
  52. {
  53. }
  54. static const char * const *
  55. in_psp_get_key_names(const in_drv_t *drv, int *count)
  56. {
  57. *count = IN_PSP_NBUTTONS;
  58. return in_psp_keys;
  59. }
  60. /* ORs result with pressed buttons */
  61. static int in_psp_update(void *drv_data, const int *binds, int *result)
  62. {
  63. int type_start = 0;
  64. int i, t, keys;
  65. keys = in_psp_get_bits();
  66. if (keys & in_psp_combo_keys) {
  67. result[IN_BINDTYPE_EMU] = in_combos_do(keys, binds, IN_PSP_NBUTTONS,
  68. in_psp_combo_keys, in_psp_combo_acts);
  69. type_start = IN_BINDTYPE_PLAYER12;
  70. }
  71. for (i = 0; keys; i++, keys >>= 1) {
  72. if (!(keys & 1))
  73. continue;
  74. for (t = type_start; t < IN_BINDTYPE_COUNT; t++)
  75. result[t] |= binds[IN_BIND_OFFS(i, t)];
  76. }
  77. return 0;
  78. }
  79. int in_psp_update_keycode(void *data, int *is_down)
  80. {
  81. static int old_val = 0;
  82. int val, diff, i;
  83. val = in_psp_get_bits();
  84. diff = val ^ old_val;
  85. if (diff == 0)
  86. return -1;
  87. /* take one bit only */
  88. for (i = 0; i < sizeof(diff)*8; i++)
  89. if (diff & (1<<i))
  90. break;
  91. old_val ^= 1 << i;
  92. if (is_down)
  93. *is_down = !!(val & (1<<i));
  94. return i;
  95. }
  96. static const struct {
  97. short key;
  98. short pbtn;
  99. } key_pbtn_map[] =
  100. {
  101. { PSP_CTRL_UP, PBTN_UP },
  102. { PSP_CTRL_DOWN, PBTN_DOWN },
  103. { PSP_CTRL_LEFT, PBTN_LEFT },
  104. { PSP_CTRL_RIGHT, PBTN_RIGHT },
  105. { PSP_CTRL_CIRCLE, PBTN_MOK },
  106. { PSP_CTRL_CROSS, PBTN_MBACK },
  107. { PSP_CTRL_TRIANGLE, PBTN_MA2 },
  108. { PSP_CTRL_SQUARE, PBTN_MA3 },
  109. { PSP_CTRL_LTRIGGER, PBTN_L },
  110. { PSP_CTRL_RTRIGGER, PBTN_R },
  111. { PSP_CTRL_SELECT, PBTN_MENU },
  112. };
  113. #define KEY_PBTN_MAP_SIZE (sizeof(key_pbtn_map) / sizeof(key_pbtn_map[0]))
  114. static int in_psp_menu_translate(void *drv_data, int keycode, char *charcode)
  115. {
  116. int i;
  117. if (keycode < 0)
  118. {
  119. /* menu -> kc */
  120. keycode = -keycode;
  121. for (i = 0; i < KEY_PBTN_MAP_SIZE; i++)
  122. if (key_pbtn_map[i].pbtn == keycode)
  123. return lg2(key_pbtn_map[i].key);
  124. }
  125. else
  126. {
  127. for (i = 0; i < KEY_PBTN_MAP_SIZE; i++)
  128. if (key_pbtn_map[i].key == 1<<keycode)
  129. return key_pbtn_map[i].pbtn;
  130. }
  131. return 0;
  132. }
  133. /* remove binds of missing keys, count remaining ones */
  134. static int in_psp_clean_binds(void *drv_data, int *binds, int *def_binds)
  135. {
  136. int i, count = 0;
  137. for (i = 0; i < IN_PSP_NBUTTONS; i++) {
  138. int t, offs;
  139. for (t = 0; t < IN_BINDTYPE_COUNT; t++) {
  140. offs = IN_BIND_OFFS(i, t);
  141. if (in_psp_keys[i] == NULL)
  142. binds[offs] = def_binds[offs] = 0;
  143. if (binds[offs])
  144. count++;
  145. }
  146. }
  147. in_combos_find(binds, IN_PSP_NBUTTONS, &in_psp_combo_keys, &in_psp_combo_acts);
  148. return count;
  149. }
  150. static const in_drv_t in_psp_drv = {
  151. .prefix = IN_PSP_PREFIX,
  152. .probe = in_psp_probe,
  153. .free = in_psp_free,
  154. .get_key_names = in_psp_get_key_names,
  155. .clean_binds = in_psp_clean_binds,
  156. .update = in_psp_update,
  157. .update_keycode = in_psp_update_keycode,
  158. .menu_translate = in_psp_menu_translate,
  159. };
  160. void in_psp_init(const struct in_default_bind *defbinds)
  161. {
  162. in_psp_combo_keys = in_psp_combo_acts = 0;
  163. /* fill keys array, converting key bitmasks to indexes */
  164. in_psp_keys[lg2(PSP_CTRL_UP)] = "Up";
  165. in_psp_keys[lg2(PSP_CTRL_LEFT)] = "Left";
  166. in_psp_keys[lg2(PSP_CTRL_DOWN)] = "Down";
  167. in_psp_keys[lg2(PSP_CTRL_RIGHT)] = "Right";
  168. in_psp_keys[lg2(PSP_CTRL_START)] = "Start";
  169. in_psp_keys[lg2(PSP_CTRL_SELECT)] = "Select";
  170. in_psp_keys[lg2(PSP_CTRL_LTRIGGER)] = "L";
  171. in_psp_keys[lg2(PSP_CTRL_RTRIGGER)] = "R";
  172. in_psp_keys[lg2(PSP_CTRL_TRIANGLE)] = "Triangle";
  173. in_psp_keys[lg2(PSP_CTRL_CIRCLE)] = "Circle";
  174. in_psp_keys[lg2(PSP_CTRL_CROSS)] = "Cross";
  175. in_psp_keys[lg2(PSP_CTRL_SQUARE)] = "Square";
  176. in_psp_keys[lg2(PSP_NUB_UP)] = "Analog up";
  177. in_psp_keys[lg2(PSP_NUB_LEFT)] = "Analog left";
  178. in_psp_keys[lg2(PSP_NUB_DOWN)] = "Analog down";
  179. in_psp_keys[lg2(PSP_NUB_RIGHT)] = "Analog right";
  180. in_register_driver(&in_psp_drv, defbinds, NULL);
  181. }