in_psp.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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. /* calculate bit number from bit mask (logarithm to the basis 2) */
  32. static int lg2(unsigned v)
  33. {
  34. /* credits to https://graphics.stanford.edu/~seander/bithacks.html */
  35. int r, s;
  36. r = (v > 0xFFFF) << 4; v >>= r;
  37. s = (v > 0xFF ) << 3; v >>= s; r |= s;
  38. s = (v > 0xF ) << 2; v >>= s; r |= s;
  39. s = (v > 0x3 ) << 1; v >>= s; r |= s;
  40. r |= (v >> 1);
  41. return r;
  42. }
  43. static unsigned in_psp_get_bits(void)
  44. {
  45. return psp_pad_read(0) & 0xf000ffff;
  46. }
  47. static void in_psp_probe(const in_drv_t *drv)
  48. {
  49. in_register(IN_PSP_PREFIX "PSP pad", -1, NULL,
  50. IN_PSP_NBUTTONS, in_psp_keys, 1);
  51. }
  52. static void in_psp_free(void *drv_data)
  53. {
  54. }
  55. static const char * const *
  56. in_psp_get_key_names(const in_drv_t *drv, int *count)
  57. {
  58. *count = IN_PSP_NBUTTONS;
  59. return in_psp_keys;
  60. }
  61. /* ORs result with pressed buttons */
  62. static int in_psp_update(void *drv_data, const int *binds, int *result)
  63. {
  64. int type_start = 0;
  65. int i, t;
  66. unsigned keys;
  67. keys = in_psp_get_bits();
  68. if (keys & in_psp_combo_keys) {
  69. result[IN_BINDTYPE_EMU] = in_combos_do(keys, binds, IN_PSP_NBUTTONS,
  70. in_psp_combo_keys, in_psp_combo_acts);
  71. type_start = IN_BINDTYPE_PLAYER12;
  72. }
  73. for (i = 0; keys; i++, keys >>= 1) {
  74. if (!(keys & 1))
  75. continue;
  76. for (t = type_start; t < IN_BINDTYPE_COUNT; t++)
  77. result[t] |= binds[IN_BIND_OFFS(i, t)];
  78. }
  79. return 0;
  80. }
  81. int in_psp_update_keycode(void *data, int *is_down)
  82. {
  83. static unsigned old_val = 0;
  84. unsigned val, diff, i;
  85. val = in_psp_get_bits();
  86. diff = val ^ old_val;
  87. if (diff == 0)
  88. return -1;
  89. /* take one bit only */
  90. for (i = 0; i < sizeof(diff)*8; i++)
  91. if (diff & (1<<i))
  92. break;
  93. old_val ^= 1 << i;
  94. if (is_down)
  95. *is_down = !!(val & (1<<i));
  96. return i;
  97. }
  98. static struct {
  99. unsigned key;
  100. int pbtn;
  101. } key_pbtn_map[] =
  102. {
  103. { PSP_CTRL_UP, PBTN_UP },
  104. { PSP_CTRL_DOWN, PBTN_DOWN },
  105. { PSP_CTRL_LEFT, PBTN_LEFT },
  106. { PSP_CTRL_RIGHT, PBTN_RIGHT },
  107. { PSP_CTRL_CIRCLE, PBTN_MOK },
  108. { PSP_CTRL_CROSS, PBTN_MBACK },
  109. { PSP_CTRL_TRIANGLE, PBTN_MA2 },
  110. { PSP_CTRL_SQUARE, PBTN_MA3 },
  111. { PSP_CTRL_LTRIGGER, PBTN_L },
  112. { PSP_CTRL_RTRIGGER, PBTN_R },
  113. { PSP_CTRL_SELECT, PBTN_MENU },
  114. };
  115. #define KEY_PBTN_MAP_SIZE (sizeof(key_pbtn_map) / sizeof(key_pbtn_map[0]))
  116. static int in_psp_menu_translate(void *drv_data, int keycode, char *charcode)
  117. {
  118. int i;
  119. if (keycode < 0)
  120. {
  121. /* menu -> kc */
  122. keycode = -keycode;
  123. for (i = 0; i < KEY_PBTN_MAP_SIZE; i++)
  124. if (key_pbtn_map[i].pbtn == keycode)
  125. return key_pbtn_map[i].key;
  126. }
  127. else
  128. {
  129. for (i = 0; i < KEY_PBTN_MAP_SIZE; i++)
  130. if (key_pbtn_map[i].key == keycode)
  131. return key_pbtn_map[i].pbtn;
  132. }
  133. return 0;
  134. }
  135. /* remove binds of missing keys, count remaining ones */
  136. static int in_psp_clean_binds(void *drv_data, int *binds, int *def_binds)
  137. {
  138. int i, count = 0;
  139. for (i = 0; i < IN_PSP_NBUTTONS; i++) {
  140. int t, offs;
  141. for (t = 0; t < IN_BINDTYPE_COUNT; t++) {
  142. offs = IN_BIND_OFFS(i, t);
  143. if (in_psp_keys[i] == NULL)
  144. binds[offs] = def_binds[offs] = 0;
  145. if (binds[offs])
  146. count++;
  147. }
  148. }
  149. in_combos_find(binds, IN_PSP_NBUTTONS, &in_psp_combo_keys, &in_psp_combo_acts);
  150. return count;
  151. }
  152. static const in_drv_t in_psp_drv = {
  153. .prefix = IN_PSP_PREFIX,
  154. .probe = in_psp_probe,
  155. .free = in_psp_free,
  156. .get_key_names = in_psp_get_key_names,
  157. .clean_binds = in_psp_clean_binds,
  158. .update = in_psp_update,
  159. .update_keycode = in_psp_update_keycode,
  160. .menu_translate = in_psp_menu_translate,
  161. };
  162. void in_psp_init(struct in_default_bind *defbinds)
  163. {
  164. int i;
  165. /* PSP keys have bit masks, Picodrive wants bit numbers */
  166. for (i = 0; defbinds[i].code; i++)
  167. defbinds[i].code = lg2(defbinds[i].code);
  168. for (i = 0; i < KEY_PBTN_MAP_SIZE; i++)
  169. key_pbtn_map[i].key = lg2(key_pbtn_map[i].key);
  170. in_psp_combo_keys = in_psp_combo_acts = 0;
  171. /* fill keys array, converting key bitmasks to bit numbers */
  172. in_psp_keys[lg2(PSP_CTRL_UP)] = "Up";
  173. in_psp_keys[lg2(PSP_CTRL_LEFT)] = "Left";
  174. in_psp_keys[lg2(PSP_CTRL_DOWN)] = "Down";
  175. in_psp_keys[lg2(PSP_CTRL_RIGHT)] = "Right";
  176. in_psp_keys[lg2(PSP_CTRL_START)] = "Start";
  177. in_psp_keys[lg2(PSP_CTRL_SELECT)] = "Select";
  178. in_psp_keys[lg2(PSP_CTRL_LTRIGGER)] = "L";
  179. in_psp_keys[lg2(PSP_CTRL_RTRIGGER)] = "R";
  180. in_psp_keys[lg2(PSP_CTRL_TRIANGLE)] = "Triangle";
  181. in_psp_keys[lg2(PSP_CTRL_CIRCLE)] = "Circle";
  182. in_psp_keys[lg2(PSP_CTRL_CROSS)] = "Cross";
  183. in_psp_keys[lg2(PSP_CTRL_SQUARE)] = "Square";
  184. in_psp_keys[lg2(PSP_NUB_UP)] = "Analog up";
  185. in_psp_keys[lg2(PSP_NUB_LEFT)] = "Analog left";
  186. in_psp_keys[lg2(PSP_NUB_DOWN)] = "Analog down";
  187. in_psp_keys[lg2(PSP_NUB_RIGHT)] = "Analog right";
  188. in_register_driver(&in_psp_drv, defbinds, NULL);
  189. }