input: add hack to allow abs-only devices
[picodrive.git] / platform / win32 / in_vk.c
1 #define RC_INVOKED // we only need defines
2 #include <winuser.h>
3 #undef RC_INVOKED
4 #include <string.h>
5
6 #include "../common/input.h"
7 #include "../common/emu.h" // array_size
8 #include "in_vk.h"
9
10 #define IN_VK_PREFIX "vk:"
11 #define IN_VK_NKEYS 0x100
12
13 static const char * const in_vk_prefix = IN_VK_PREFIX;
14 static const char * const in_vk_keys[IN_VK_NKEYS] = {
15         [0 ... (IN_VK_NKEYS - 1)] = NULL,
16         [VK_LBUTTON] = "LBUTTON",       [VK_RBUTTON] = "RBUTTON",
17         [VK_TAB] = "TAB",               [VK_RETURN] = "RETURN",
18         [VK_SHIFT] = "SHIFT",           [VK_CONTROL] = "CONTROL",
19         [VK_LEFT] = "LEFT",             [VK_UP] = "UP",
20         [VK_RIGHT] = "RIGHT",           [VK_DOWN] = "DOWN",
21         [VK_SPACE] = "SPACE",
22 };
23
24 // additional player12 keys
25 int in_vk_add_pl12;
26
27 // up to 4, keyboards rarely allow more
28 static int in_vk_keys_down[4];
29
30 /*
31 #define VK_END  35
32 #define VK_HOME 36
33 #define VK_INSERT       45
34 #define VK_DELETE       46
35 #define VK_NUMPAD0      0x60
36 #define VK_NUMPAD1      0x61
37 #define VK_NUMPAD2      0x62
38 #define VK_NUMPAD3      0x63
39 #define VK_NUMPAD4      0x64
40 #define VK_NUMPAD5      0x65
41 #define VK_NUMPAD6      0x66
42 #define VK_NUMPAD7      0x67
43 #define VK_NUMPAD8      0x68
44 #define VK_NUMPAD9      0x69
45 #define VK_MULTIPLY     0x6A
46 #define VK_ADD  0x6B
47 #define VK_SEPARATOR    0x6C
48 #define VK_SUBTRACT     0x6D
49 #define VK_DECIMAL      0x6E
50 #define VK_DIVIDE       0x6F
51 #define VK_F1   0x70
52 #define VK_F2   0x71
53 #define VK_F3   0x72
54 #define VK_F4   0x73
55 #define VK_F5   0x74
56 #define VK_F6   0x75
57 #define VK_F7   0x76
58 #define VK_F8   0x77
59 #define VK_F9   0x78
60 #define VK_F10  0x79
61 #define VK_F11  0x7A
62 #define VK_F12  0x7B
63 */
64
65 static void in_vk_probe(void)
66 {
67         memset(in_vk_keys_down, 0, sizeof(in_vk_keys_down));
68         in_register(IN_VK_PREFIX "vk", IN_DRVID_VK, -1, (void *)1, IN_VK_NKEYS, NULL, 0);
69 }
70
71 static int in_vk_get_bind_count(void)
72 {
73         return IN_VK_NKEYS;
74 }
75
76 /* ORs result with pressed buttons */
77 int in_vk_update(void *drv_data, const int *binds, int *result)
78 {
79         int i, t, k;
80
81         for (i = 0; i < array_size(in_vk_keys_down); i++) {
82                 k = in_vk_keys_down[i];
83                 if (!k)
84                         continue;
85
86                 for (t = 0; t < IN_BINDTYPE_COUNT; t++)
87                         result[t] |= binds[IN_BIND_OFFS(k, t)];
88         }
89
90         result[IN_BINDTYPE_PLAYER12] |= in_vk_add_pl12;
91
92         return 0;
93 }
94
95 void in_vk_keydown(int kc)
96 {
97         int i;
98
99         // search
100         for (i = 0; i < array_size(in_vk_keys_down); i++)
101                 if (in_vk_keys_down[i] == kc)
102                         return;
103
104         // do
105         for (i = 0; i < array_size(in_vk_keys_down); i++) {
106                 if (in_vk_keys_down[i] == 0) {
107                         in_vk_keys_down[i] = kc;
108                         return;
109                 }
110         }
111 }
112
113 void in_vk_keyup(int kc)
114 {
115         int i;
116         for (i = 0; i < array_size(in_vk_keys_down); i++)
117                 if (in_vk_keys_down[i] == kc)
118                         in_vk_keys_down[i] = 0;
119 }
120
121 static int in_vk_update_keycode(void *data, int *is_down)
122 {
123         return 0;
124 }
125
126 static const struct {
127         short key;
128         short pbtn;
129 } key_pbtn_map[] =
130 {
131         { VK_UP,        PBTN_UP },
132         { VK_DOWN,      PBTN_DOWN },
133         { VK_LEFT,      PBTN_LEFT },
134         { VK_RIGHT,     PBTN_RIGHT },
135         { VK_RETURN,    PBTN_MOK },
136 /*
137         { BTN_X,        PBTN_MBACK },
138         { BTN_A,        PBTN_MA2 },
139         { BTN_Y,        PBTN_MA3 },
140         { BTN_L,        PBTN_L },
141         { BTN_R,        PBTN_R },
142         { BTN_SELECT,   PBTN_MENU },
143 */
144 };
145
146 #define KEY_PBTN_MAP_SIZE (sizeof(key_pbtn_map) / sizeof(key_pbtn_map[0]))
147
148 static int in_vk_menu_translate(void *drv_data, int keycode)
149 {
150         int i;
151         if (keycode < 0)
152         {
153                 /* menu -> kc */
154                 keycode = -keycode;
155                 for (i = 0; i < KEY_PBTN_MAP_SIZE; i++)
156                         if (key_pbtn_map[i].pbtn == keycode)
157                                 return key_pbtn_map[i].key;
158         }
159         else
160         {
161                 for (i = 0; i < KEY_PBTN_MAP_SIZE; i++)
162                         if (key_pbtn_map[i].key == keycode)
163                                 return key_pbtn_map[i].pbtn;
164         }
165
166         return 0;
167 }
168
169 static int in_vk_get_key_code(const char *key_name)
170 {
171         int i;
172
173         if (key_name[1] == 0 && 'A' <= key_name[0] && key_name[0] <= 'Z')
174                 return key_name[0];
175
176         for (i = 0; i < IN_VK_NKEYS; i++) {
177                 const char *k = in_vk_keys[i];
178                 if (k != NULL && strcasecmp(k, key_name) == 0)
179                         return i;
180         }
181
182         return -1;
183 }
184
185 static const char *in_vk_get_key_name(int keycode)
186 {
187         const char *name = NULL;
188         static char buff[4];
189
190         if ('A' <= keycode && keycode < 'Z') {
191                 buff[0] = keycode;
192                 buff[1] = 0;
193                 return buff;
194         }
195
196         if (0 <= keycode && keycode < IN_VK_NKEYS)
197                 name = in_vk_keys[keycode];
198         if (name == NULL)
199                 name = "Unkn";
200         
201         return name;
202 }
203
204 static const struct {
205         short code;
206         char btype;
207         char bit;
208 } in_vk_def_binds[] =
209 {
210         /* MXYZ SACB RLDU */
211         { VK_UP,        IN_BINDTYPE_PLAYER12, 0 },
212         { VK_DOWN,      IN_BINDTYPE_PLAYER12, 1 },
213         { VK_LEFT,      IN_BINDTYPE_PLAYER12, 2 },
214         { VK_RIGHT,     IN_BINDTYPE_PLAYER12, 3 },
215         { 'S',          IN_BINDTYPE_PLAYER12, 4 },      /* B */
216         { 'D',          IN_BINDTYPE_PLAYER12, 5 },      /* C */
217         { 'A',          IN_BINDTYPE_PLAYER12, 6 },      /* A */
218         { VK_RETURN,    IN_BINDTYPE_PLAYER12, 7 },
219         { 'E',          IN_BINDTYPE_PLAYER12, 8 },      /* Z */
220         { 'W',          IN_BINDTYPE_PLAYER12, 9 },      /* Y */
221         { 'Q',          IN_BINDTYPE_PLAYER12,10 },      /* X */
222         { 'R',          IN_BINDTYPE_PLAYER12,11 },      /* M */
223 /*
224         { BTN_SELECT,   IN_BINDTYPE_EMU, PEVB_MENU },
225 //      { BTN_Y,        IN_BINDTYPE_EMU, PEVB_SWITCH_RND },
226         { BTN_L,        IN_BINDTYPE_EMU, PEVB_STATE_SAVE },
227         { BTN_R,        IN_BINDTYPE_EMU, PEVB_STATE_LOAD },
228         { BTN_VOL_UP,   IN_BINDTYPE_EMU, PEVB_VOL_UP },
229         { BTN_VOL_DOWN, IN_BINDTYPE_EMU, PEVB_VOL_DOWN },
230 */
231 };
232
233 #define DEF_BIND_COUNT (sizeof(in_vk_def_binds) / sizeof(in_vk_def_binds[0]))
234
235 static void in_vk_get_def_binds(int *binds)
236 {
237         int i;
238
239         for (i = 0; i < DEF_BIND_COUNT; i++)
240                 binds[IN_BIND_OFFS(in_vk_def_binds[i].code, in_vk_def_binds[i].btype)] =
241                         1 << in_vk_def_binds[i].bit;
242 }
243
244 /* remove binds of missing keys, count remaining ones */
245 static int in_vk_clean_binds(void *drv_data, int *binds, int *def_binds)
246 {
247         int i, count = 0;
248
249         for (i = 0; i < IN_VK_NKEYS; i++) {
250                 int t, offs;
251                 for (t = 0; t < IN_BINDTYPE_COUNT; t++) {
252                         offs = IN_BIND_OFFS(i, t);
253                         if (strcmp(in_vk_get_key_name(i), "Unkn") == 0)
254                                 binds[offs] = def_binds[offs] = 0;
255                         if (binds[offs])
256                                 count++;
257                 }
258         }
259
260         return count;
261 }
262
263 void in_vk_init(void *vdrv)
264 {
265         in_drv_t *drv = vdrv;
266
267         drv->prefix = in_vk_prefix;
268         drv->probe = in_vk_probe;
269         drv->get_bind_count = in_vk_get_bind_count;
270         drv->get_def_binds = in_vk_get_def_binds;
271         drv->clean_binds = in_vk_clean_binds;
272         drv->menu_translate = in_vk_menu_translate;
273         drv->get_key_code = in_vk_get_key_code;
274         drv->get_key_name = in_vk_get_key_name;
275         drv->update_keycode = in_vk_update_keycode;
276 }
277