Mercurial > repos > blastem
comparison io.c @ 907:b5d35222047e
Mega mouse support is mostly done
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 28 Nov 2015 21:27:21 -0800 |
parents | 0e5f9d6135be |
children | c030e4af32b7 |
comparison
equal
deleted
inserted
replaced
906:8cf57c6558ed | 907:b5d35222047e |
---|---|
42 BIND_GAMEPAD3, | 42 BIND_GAMEPAD3, |
43 BIND_GAMEPAD4, | 43 BIND_GAMEPAD4, |
44 BIND_GAMEPAD5, | 44 BIND_GAMEPAD5, |
45 BIND_GAMEPAD6, | 45 BIND_GAMEPAD6, |
46 BIND_GAMEPAD7, | 46 BIND_GAMEPAD7, |
47 BIND_GAMEPAD8 | 47 BIND_GAMEPAD8, |
48 BIND_MOUSE1, | |
49 BIND_MOUSE2, | |
50 BIND_MOUSE3, | |
51 BIND_MOUSE4, | |
52 BIND_MOUSE5, | |
53 BIND_MOUSE6, | |
54 BIND_MOUSE7, | |
55 BIND_MOUSE8 | |
48 }; | 56 }; |
49 | 57 |
50 typedef enum { | 58 typedef enum { |
51 UI_DEBUG_MODE_INC, | 59 UI_DEBUG_MODE_INC, |
52 UI_DEBUG_PAL_INC, | 60 UI_DEBUG_PAL_INC, |
70 keybinding bindings[4]; | 78 keybinding bindings[4]; |
71 uint8_t state; | 79 uint8_t state; |
72 } joydpad; | 80 } joydpad; |
73 | 81 |
74 typedef struct { | 82 typedef struct { |
75 io_port *port; | 83 io_port *motion_port; |
76 uint8_t mode; | 84 keybinding buttons[MAX_MOUSE_BUTTONS]; |
85 uint8_t bind_type; | |
86 uint8_t motion_mode; | |
77 } mousebinding; | 87 } mousebinding; |
78 | 88 |
79 keybinding * bindings[0x10000]; | 89 keybinding * bindings[0x10000]; |
80 keybinding * joybindings[MAX_JOYSTICKS]; | 90 keybinding * joybindings[MAX_JOYSTICKS]; |
81 joydpad * joydpads[MAX_JOYSTICKS]; | 91 joydpad * joydpads[MAX_JOYSTICKS]; |
82 mousebinding *mice[MAX_MICE]; | 92 mousebinding mice[MAX_MICE]; |
83 const uint8_t dpadbits[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT}; | 93 const uint8_t dpadbits[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT}; |
84 | 94 |
85 void bind_key(int keycode, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value) | 95 void bind_key(int keycode, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value) |
86 { | 96 { |
87 int bucket = keycode >> 15 & 0xFFFF; | 97 int bucket = keycode >> 15 & 0xFFFF; |
152 #define BUTTON_A GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_NONE, 0x10) | 162 #define BUTTON_A GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_NONE, 0x10) |
153 #define BUTTON_B GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x10) | 163 #define BUTTON_B GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x10) |
154 #define BUTTON_START GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_NONE, 0x20) | 164 #define BUTTON_START GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_NONE, 0x20) |
155 #define BUTTON_C GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x20) | 165 #define BUTTON_C GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x20) |
156 | 166 |
167 #define PSEUDO_BUTTON_MOTION 0xFFFF | |
168 #define MOUSE_LEFT 1 | |
169 #define MOUSE_RIGHT 2 | |
170 #define MOUSE_MIDDLE 4 | |
171 #define MOUSE_START 8 | |
172 | |
173 | |
174 | |
157 void bind_gamepad(int keycode, int gamepadnum, int button) | 175 void bind_gamepad(int keycode, int gamepadnum, int button) |
158 { | 176 { |
159 | 177 |
160 if (gamepadnum < 1 || gamepadnum > 8) { | 178 if (gamepadnum < 1 || gamepadnum > 8) { |
161 return; | 179 return; |
197 bind_dpad(joystick, dpad, direction, BIND_UI, action, 0, param); | 215 bind_dpad(joystick, dpad, direction, BIND_UI, action, 0, param); |
198 } | 216 } |
199 | 217 |
200 void handle_binding_down(keybinding * binding) | 218 void handle_binding_down(keybinding * binding) |
201 { | 219 { |
202 if (binding->bind_type >= BIND_GAMEPAD1) | 220 if (binding->bind_type >= BIND_GAMEPAD1 && binding->bind_type <= BIND_GAMEPAD8) |
203 { | 221 { |
204 if (binding->subtype_a <= GAMEPAD_EXTRA && binding->port) { | 222 if (binding->subtype_a <= GAMEPAD_EXTRA && binding->port) { |
205 binding->port->input[binding->subtype_a] |= binding->value; | 223 binding->port->input[binding->subtype_a] |= binding->value; |
206 } | 224 } |
207 if (binding->subtype_b <= GAMEPAD_EXTRA && binding->port) { | 225 if (binding->subtype_b <= GAMEPAD_EXTRA && binding->port) { |
208 binding->port->input[binding->subtype_b] |= binding->value; | 226 binding->port->input[binding->subtype_b] |= binding->value; |
227 } | |
228 } | |
229 else if (binding->bind_type >= BIND_MOUSE1 && binding->bind_type <= BIND_MOUSE8) | |
230 { | |
231 if (binding->port) { | |
232 binding->port->input[0] |= binding->value; | |
209 } | 233 } |
210 } | 234 } |
211 } | 235 } |
212 | 236 |
213 void handle_keydown(int keycode) | 237 void handle_keydown(int keycode) |
228 } | 252 } |
229 keybinding * binding = joybindings[joystick] + button; | 253 keybinding * binding = joybindings[joystick] + button; |
230 handle_binding_down(binding); | 254 handle_binding_down(binding); |
231 } | 255 } |
232 | 256 |
257 void handle_mousedown(int mouse, int button) | |
258 { | |
259 if (mouse >= MAX_MICE || button > MAX_MOUSE_BUTTONS || button <= 0) { | |
260 return; | |
261 } | |
262 keybinding * binding = mice[mouse].buttons + button - 1; | |
263 handle_binding_down(binding); | |
264 } | |
265 | |
233 uint8_t ui_debug_mode = 0; | 266 uint8_t ui_debug_mode = 0; |
234 uint8_t ui_debug_pal = 0; | 267 uint8_t ui_debug_pal = 0; |
235 | 268 |
236 int current_speed = 0; | 269 int current_speed = 0; |
237 int num_speeds = 1; | 270 int num_speeds = 1; |
241 { | 274 { |
242 switch(binding->bind_type) | 275 switch(binding->bind_type) |
243 { | 276 { |
244 case BIND_GAMEPAD1: | 277 case BIND_GAMEPAD1: |
245 case BIND_GAMEPAD2: | 278 case BIND_GAMEPAD2: |
279 case BIND_GAMEPAD3: | |
280 case BIND_GAMEPAD4: | |
281 case BIND_GAMEPAD5: | |
282 case BIND_GAMEPAD6: | |
283 case BIND_GAMEPAD7: | |
284 case BIND_GAMEPAD8: | |
246 if (binding->subtype_a <= GAMEPAD_EXTRA && binding->port) { | 285 if (binding->subtype_a <= GAMEPAD_EXTRA && binding->port) { |
247 binding->port->input[binding->subtype_a] &= ~binding->value; | 286 binding->port->input[binding->subtype_a] &= ~binding->value; |
248 } | 287 } |
249 if (binding->subtype_b <= GAMEPAD_EXTRA && binding->port) { | 288 if (binding->subtype_b <= GAMEPAD_EXTRA && binding->port) { |
250 binding->port->input[binding->subtype_b] &= ~binding->value; | 289 binding->port->input[binding->subtype_b] &= ~binding->value; |
290 } | |
291 break; | |
292 case BIND_MOUSE1: | |
293 case BIND_MOUSE2: | |
294 case BIND_MOUSE3: | |
295 case BIND_MOUSE4: | |
296 case BIND_MOUSE5: | |
297 case BIND_MOUSE6: | |
298 case BIND_MOUSE7: | |
299 case BIND_MOUSE8: | |
300 if (binding->port) { | |
301 binding->port->input[0] &= ~binding->value; | |
251 } | 302 } |
252 break; | 303 break; |
253 case BIND_UI: | 304 case BIND_UI: |
254 switch (binding->subtype_a) | 305 switch (binding->subtype_a) |
255 { | 306 { |
342 handle_binding_up(dpad->bindings + i); | 393 handle_binding_up(dpad->bindings + i); |
343 } | 394 } |
344 } | 395 } |
345 } | 396 } |
346 | 397 |
398 void handle_mouseup(int mouse, int button) | |
399 { | |
400 if (mouse >= MAX_MICE || button > MAX_MOUSE_BUTTONS || button <= 0) { | |
401 return; | |
402 } | |
403 keybinding * binding = mice[mouse].buttons + button - 1; | |
404 handle_binding_up(binding); | |
405 } | |
406 | |
347 void handle_mouse_moved(int mouse, uint16_t x, uint16_t y) | 407 void handle_mouse_moved(int mouse, uint16_t x, uint16_t y) |
348 { | 408 { |
349 printf("mouse motion: %d - (%d, %d)\n", mouse, x, y); | 409 if (mouse >= MAX_MICE || !mice[mouse].motion_port) { |
350 if (mouse >= MAX_MICE || !mice[mouse]) { | 410 return; |
351 return; | 411 } |
352 } | 412 //TODO: relative mode |
353 | 413 //TODO: scale based on window size |
354 } | 414 mice[mouse].motion_port->device.mouse.cur_x = x; |
355 | 415 mice[mouse].motion_port->device.mouse.cur_y = y; |
356 int parse_binding_target(char * target, tern_node * padbuttons, int * ui_out, int * padnum_out, int * padbutton_out) | 416 } |
357 { | 417 |
358 int gpadslen = strlen("gamepads."); | 418 int parse_binding_target(char * target, tern_node * padbuttons, tern_node *mousebuttons, int * ui_out, int * padnum_out, int * padbutton_out) |
419 { | |
420 const int gpadslen = strlen("gamepads."); | |
421 const int mouselen = strlen("mouse."); | |
359 if (!strncmp(target, "gamepads.", gpadslen)) { | 422 if (!strncmp(target, "gamepads.", gpadslen)) { |
360 if (target[gpadslen] >= '1' && target[gpadslen] <= '8') { | 423 if (target[gpadslen] >= '1' && target[gpadslen] <= '8') { |
361 int padnum = target[gpadslen] - '0'; | 424 int padnum = target[gpadslen] - '0'; |
362 int button = tern_find_int(padbuttons, target + gpadslen + 1, 0); | 425 int button = tern_find_int(padbuttons, target + gpadslen + 1, 0); |
363 if (button) { | 426 if (button) { |
364 *padnum_out = padnum; | 427 *padnum_out = padnum; |
365 *padbutton_out = button; | 428 *padbutton_out = button; |
366 return 1; | 429 return BIND_GAMEPAD1; |
367 } else { | 430 } else { |
368 if (target[gpadslen+1]) { | 431 if (target[gpadslen+1]) { |
369 warning("Gamepad mapping string '%s' refers to an invalid button '%s'\n", target, target + gpadslen + 1); | 432 warning("Gamepad mapping string '%s' refers to an invalid button '%s'\n", target, target + gpadslen + 1); |
370 } else { | 433 } else { |
371 warning("Gamepad mapping string '%s' has no button component\n", target); | 434 warning("Gamepad mapping string '%s' has no button component\n", target); |
372 } | 435 } |
373 } | 436 } |
374 } else { | 437 } else { |
375 warning("Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]); | 438 warning("Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]); |
439 } | |
440 } else if(!strncmp(target, "mouse.", mouselen)) { | |
441 if (target[mouselen] >= '1' && target[mouselen] <= '8') { | |
442 int mousenum = target[mouselen] - '0'; | |
443 int button = tern_find_int(mousebuttons, target + mouselen + 1, 0); | |
444 if (button) { | |
445 *padnum_out = mousenum; | |
446 *padbutton_out = button; | |
447 return BIND_MOUSE1; | |
448 } else { | |
449 if (target[mouselen+1]) { | |
450 warning("Mouse mapping string '%s' refers to an invalid button '%s'\n", target, target + mouselen + 1); | |
451 } else { | |
452 warning("Mouse mapping string '%s' has no button component\n", target); | |
453 } | |
454 } | |
455 } else { | |
456 warning("Gamepad mapping string '%s' refers to an invalid mouse number %c\n", target, target[mouselen]); | |
376 } | 457 } |
377 } else if(!strncmp(target, "ui.", strlen("ui."))) { | 458 } else if(!strncmp(target, "ui.", strlen("ui."))) { |
378 *padbutton_out = 0; | 459 *padbutton_out = 0; |
379 if (!strcmp(target + 3, "vdp_debug_mode")) { | 460 if (!strcmp(target + 3, "vdp_debug_mode")) { |
380 *ui_out = UI_DEBUG_MODE_INC; | 461 *ui_out = UI_DEBUG_MODE_INC; |
395 *ui_out = UI_EXIT; | 476 *ui_out = UI_EXIT; |
396 } else { | 477 } else { |
397 warning("Unreconized UI binding type %s\n", target); | 478 warning("Unreconized UI binding type %s\n", target); |
398 return 0; | 479 return 0; |
399 } | 480 } |
400 return 2; | 481 return BIND_UI; |
401 } else { | 482 } else { |
402 warning("Unrecognized binding type %s\n", target); | 483 warning("Unrecognized binding type %s\n", target); |
403 } | 484 } |
404 return 0; | 485 return 0; |
405 } | 486 } |
406 | 487 |
407 void process_keys(tern_node * cur, tern_node * special, tern_node * padbuttons, char * prefix) | 488 void process_keys(tern_node * cur, tern_node * special, tern_node * padbuttons, tern_node *mousebuttons, char * prefix) |
408 { | 489 { |
409 char * curstr = NULL; | 490 char * curstr = NULL; |
410 int len; | 491 int len; |
411 if (!cur) { | 492 if (!cur) { |
412 return; | 493 return; |
421 len = 0; | 502 len = 0; |
422 } | 503 } |
423 curstr[len] = cur->el; | 504 curstr[len] = cur->el; |
424 curstr[len+1] = 0; | 505 curstr[len+1] = 0; |
425 if (cur->el) { | 506 if (cur->el) { |
426 process_keys(cur->straight.next, special, padbuttons, curstr); | 507 process_keys(cur->straight.next, special, padbuttons, mousebuttons, curstr); |
427 } else { | 508 } else { |
428 int keycode = tern_find_int(special, curstr, 0); | 509 int keycode = tern_find_int(special, curstr, 0); |
429 if (!keycode) { | 510 if (!keycode) { |
430 keycode = curstr[0]; | 511 keycode = curstr[0]; |
431 if (curstr[1] != 0) { | 512 if (curstr[1] != 0) { |
432 warning("%s is not recognized as a key identifier, truncating to %c\n", curstr, curstr[0]); | 513 warning("%s is not recognized as a key identifier, truncating to %c\n", curstr, curstr[0]); |
433 } | 514 } |
434 } | 515 } |
435 char * target = cur->straight.value.ptrval; | 516 char * target = cur->straight.value.ptrval; |
436 int ui_func, padnum, button; | 517 int ui_func, padnum, button; |
437 int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button); | 518 int bindtype = parse_binding_target(target, padbuttons, mousebuttons, &ui_func, &padnum, &button); |
438 if (bindtype == 1) { | 519 if (bindtype == BIND_GAMEPAD1) { |
439 bind_gamepad(keycode, padnum, button); | 520 bind_gamepad(keycode, padnum, button); |
440 } else if(bindtype == 2) { | 521 } else if(bindtype == BIND_UI) { |
441 bind_ui(keycode, ui_func, button); | 522 bind_ui(keycode, ui_func, button); |
442 } | 523 } |
443 } | 524 } |
444 process_keys(cur->left, special, padbuttons, prefix); | 525 process_keys(cur->left, special, padbuttons, mousebuttons, prefix); |
445 process_keys(cur->right, special, padbuttons, prefix); | 526 process_keys(cur->right, special, padbuttons, mousebuttons, prefix); |
446 if (curstr && len) { | 527 if (curstr && len) { |
447 free(curstr); | 528 free(curstr); |
448 } | 529 } |
449 } | 530 } |
450 | 531 |
518 } else { | 599 } else { |
519 port->device_type = IO_GAMEPAD6; | 600 port->device_type = IO_GAMEPAD6; |
520 } | 601 } |
521 port->device.pad.gamepad_num = device_type[gamepad_len+2] - '1'; | 602 port->device.pad.gamepad_num = device_type[gamepad_len+2] - '1'; |
522 } else if(!strncmp(device_type, "mouse", mouse_len)) { | 603 } else if(!strncmp(device_type, "mouse", mouse_len)) { |
523 //TODO: do something with mouse number | |
524 port->device_type = IO_MOUSE; | 604 port->device_type = IO_MOUSE; |
605 port->device.mouse.mouse_num = device_type[mouse_len+1] - '1'; | |
606 port->device.mouse.last_read_x = 0; | |
607 port->device.mouse.last_read_y = 0; | |
608 port->device.mouse.cur_x = 0; | |
609 port->device.mouse.cur_y = 0; | |
610 port->device.mouse.tr_counter = 0; | |
525 } else if(!strcmp(device_type, "sega_parallel")) { | 611 } else if(!strcmp(device_type, "sega_parallel")) { |
526 port->device_type = IO_SEGA_PARALLEL; | 612 port->device_type = IO_SEGA_PARALLEL; |
527 port->device.stream.data_fd = -1; | 613 port->device.stream.data_fd = -1; |
528 port->device.stream.listen_fd = -1; | 614 port->device.stream.listen_fd = -1; |
529 } else if(!strcmp(device_type, "generic")) { | 615 } else if(!strcmp(device_type, "generic")) { |
641 | 727 |
642 void map_bindings(io_port *ports, keybinding *bindings, int numbindings) | 728 void map_bindings(io_port *ports, keybinding *bindings, int numbindings) |
643 { | 729 { |
644 for (int i = 0; i < numbindings; i++) | 730 for (int i = 0; i < numbindings; i++) |
645 { | 731 { |
646 if (bindings[i].bind_type >= BIND_GAMEPAD1) | 732 if (bindings[i].bind_type >= BIND_GAMEPAD1 && bindings[i].bind_type <= BIND_GAMEPAD8) |
647 { | 733 { |
648 int num = bindings[i].bind_type - BIND_GAMEPAD1; | 734 int num = bindings[i].bind_type - BIND_GAMEPAD1; |
649 for (int j = 0; j < 3; j++) | 735 for (int j = 0; j < 3; j++) |
650 { | 736 { |
651 if ((ports[j].device_type == IO_GAMEPAD3 | 737 if ((ports[j].device_type == IO_GAMEPAD3 |
657 bindings[i].port = ports + j; | 743 bindings[i].port = ports + j; |
658 break; | 744 break; |
659 } | 745 } |
660 } | 746 } |
661 } | 747 } |
748 else if (bindings[i].bind_type >= BIND_MOUSE1 && bindings[i].bind_type <= BIND_MOUSE8) | |
749 { | |
750 int num = bindings[i].bind_type - BIND_MOUSE1; | |
751 for (int j = 0; j < 3; j++) | |
752 { | |
753 if (ports[j].device_type == IO_MOUSE && ports[j].device.mouse.mouse_num == num) | |
754 { | |
755 memset(ports[j].input, 0, sizeof(ports[j].input)); | |
756 bindings[i].port = ports + j; | |
757 break; | |
758 } | |
759 } | |
760 } | |
761 } | |
762 } | |
763 | |
764 typedef struct { | |
765 tern_node *padbuttons; | |
766 tern_node *mousebuttons; | |
767 int mouseidx; | |
768 } pmb_state; | |
769 | |
770 void process_mouse_button(char *buttonstr, tern_val value, void *data) | |
771 { | |
772 pmb_state *state = data; | |
773 int buttonnum = atoi(buttonstr); | |
774 if (buttonnum < 1 || buttonnum > MAX_MOUSE_BUTTONS) { | |
775 warning("Mouse button %s is out of the supported range of 1-8\n", buttonstr); | |
776 return; | |
777 } | |
778 buttonnum--; | |
779 int ui_func, devicenum, button; | |
780 int bindtype = parse_binding_target(value.ptrval, state->padbuttons, state->mousebuttons, &ui_func, &devicenum, &button); | |
781 switch (bindtype) | |
782 { | |
783 case BIND_UI: | |
784 mice[state->mouseidx].buttons[buttonnum].subtype_a = ui_func; | |
785 break; | |
786 case BIND_GAMEPAD1: | |
787 mice[state->mouseidx].buttons[buttonnum].subtype_a = button >> 12; | |
788 mice[state->mouseidx].buttons[buttonnum].subtype_b = button >> 8 & 0xF; | |
789 mice[state->mouseidx].buttons[buttonnum].value = button & 0xFF; | |
790 break; | |
791 case BIND_MOUSE1: | |
792 mice[state->mouseidx].buttons[buttonnum].value = button & 0xFF; | |
793 break; | |
794 } | |
795 if (bindtype != BIND_UI) { | |
796 bindtype += devicenum-1; | |
797 } | |
798 mice[state->mouseidx].buttons[buttonnum].bind_type = bindtype; | |
799 | |
800 } | |
801 | |
802 void process_mouse(char *mousenum, tern_val value, void *data) | |
803 { | |
804 tern_node **buttonmaps = data; | |
805 tern_node *mousedef = tern_get_node(value); | |
806 tern_node *padbuttons = buttonmaps[0]; | |
807 tern_node *mousebuttons = buttonmaps[1]; | |
808 | |
809 if (!mousedef) { | |
810 warning("Binding for mouse %s is a scalar!\n", mousenum); | |
811 return; | |
812 } | |
813 int mouseidx = atoi(mousenum); | |
814 if (mouseidx < 0 || mouseidx >= MAX_MICE) { | |
815 warning("Mouse numbers must be between 0 and %d, but %d is not\n", MAX_MICE, mouseidx); | |
816 return; | |
817 } | |
818 char *motion = tern_find_ptr(mousedef, "motion"); | |
819 if (motion) { | |
820 int ui_func,devicenum,button; | |
821 int bindtype = parse_binding_target(motion, padbuttons, mousebuttons, &ui_func, &devicenum, &button); | |
822 if (bindtype != BIND_UI) { | |
823 bindtype += devicenum-1; | |
824 } | |
825 if (button == PSEUDO_BUTTON_MOTION) { | |
826 mice[mouseidx].bind_type = bindtype; | |
827 } else { | |
828 warning("Mouse motion can't be bound to target %s\n", motion); | |
829 } | |
830 } | |
831 tern_node *buttons = tern_get_node(tern_find_path(mousedef, "buttons\0\0")); | |
832 if (buttons) { | |
833 pmb_state state = {padbuttons, mousebuttons, mouseidx}; | |
834 tern_foreach(buttons, process_mouse_button, &state); | |
662 } | 835 } |
663 } | 836 } |
664 | 837 |
665 void set_keybindings(io_port *ports) | 838 void set_keybindings(io_port *ports) |
666 { | 839 { |
687 padbuttons = tern_insert_int(padbuttons, ".x", BUTTON_X); | 860 padbuttons = tern_insert_int(padbuttons, ".x", BUTTON_X); |
688 padbuttons = tern_insert_int(padbuttons, ".y", BUTTON_Y); | 861 padbuttons = tern_insert_int(padbuttons, ".y", BUTTON_Y); |
689 padbuttons = tern_insert_int(padbuttons, ".z", BUTTON_Z); | 862 padbuttons = tern_insert_int(padbuttons, ".z", BUTTON_Z); |
690 padbuttons = tern_insert_int(padbuttons, ".start", BUTTON_START); | 863 padbuttons = tern_insert_int(padbuttons, ".start", BUTTON_START); |
691 padbuttons = tern_insert_int(padbuttons, ".mode", BUTTON_MODE); | 864 padbuttons = tern_insert_int(padbuttons, ".mode", BUTTON_MODE); |
865 | |
866 tern_node *mousebuttons = tern_insert_int(NULL, ".left", MOUSE_LEFT); | |
867 mousebuttons = tern_insert_int(mousebuttons, ".middle", MOUSE_MIDDLE); | |
868 mousebuttons = tern_insert_int(mousebuttons, ".right", MOUSE_RIGHT); | |
869 mousebuttons = tern_insert_int(mousebuttons, ".start", MOUSE_START); | |
870 mousebuttons = tern_insert_int(mousebuttons, ".motion", PSEUDO_BUTTON_MOTION); | |
692 | 871 |
693 tern_node * keys = tern_get_node(tern_find_path(config, "bindings\0keys\0")); | 872 tern_node * keys = tern_get_node(tern_find_path(config, "bindings\0keys\0")); |
694 process_keys(keys, special, padbuttons, NULL); | 873 process_keys(keys, special, padbuttons, mousebuttons, NULL); |
695 char numstr[] = "00"; | 874 char numstr[] = "00"; |
696 tern_node * pads = tern_get_node(tern_find_path(config, "bindings\0pads\0")); | 875 tern_node * pads = tern_get_node(tern_find_path(config, "bindings\0pads\0")); |
697 if (pads) { | 876 if (pads) { |
698 for (int i = 0; i < 100 && i < render_num_joysticks(); i++) | 877 for (int i = 0; i < 100 && i < render_num_joysticks(); i++) |
699 { | 878 { |
718 int dirnums[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT}; | 897 int dirnums[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT}; |
719 for (int dir = 0; dir < sizeof(dirs)/sizeof(dirs[0]); dir++) { | 898 for (int dir = 0; dir < sizeof(dirs)/sizeof(dirs[0]); dir++) { |
720 char * target = tern_find_ptr(pad_dpad, dirs[dir]); | 899 char * target = tern_find_ptr(pad_dpad, dirs[dir]); |
721 if (target) { | 900 if (target) { |
722 int ui_func, padnum, button; | 901 int ui_func, padnum, button; |
723 int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button); | 902 int bindtype = parse_binding_target(target, padbuttons, mousebuttons, &ui_func, &padnum, &button); |
724 if (bindtype == 1) { | 903 if (bindtype == BIND_GAMEPAD1) { |
725 bind_dpad_gamepad(i, dpad, dirnums[dir], padnum, button); | 904 bind_dpad_gamepad(i, dpad, dirnums[dir], padnum, button); |
726 } else if (bindtype == 2) { | 905 } else if (bindtype == BIND_UI) { |
727 bind_dpad_ui(i, dpad, dirnums[dir], ui_func, button); | 906 bind_dpad_ui(i, dpad, dirnums[dir], ui_func, button); |
728 } | 907 } |
729 } | 908 } |
730 } | 909 } |
731 } | 910 } |
742 numstr[1] = but%10 + '0'; | 921 numstr[1] = but%10 + '0'; |
743 } | 922 } |
744 char * target = tern_find_ptr(button_node, numstr); | 923 char * target = tern_find_ptr(button_node, numstr); |
745 if (target) { | 924 if (target) { |
746 int ui_func, padnum, button; | 925 int ui_func, padnum, button; |
747 int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button); | 926 int bindtype = parse_binding_target(target, padbuttons, mousebuttons, &ui_func, &padnum, &button); |
748 if (bindtype == 1) { | 927 if (bindtype == BIND_GAMEPAD1) { |
749 bind_button_gamepad(i, but, padnum, button); | 928 bind_button_gamepad(i, but, padnum, button); |
750 } else if (bindtype == 2) { | 929 } else if (bindtype == BIND_UI) { |
751 bind_button_ui(i, but, ui_func, button); | 930 bind_button_ui(i, but, ui_func, button); |
752 } | 931 } |
753 } | 932 } |
754 } | 933 } |
755 } | 934 } |
756 } | 935 } |
757 } | 936 } |
937 } | |
938 memset(mice, 0, sizeof(mice)); | |
939 tern_node * mice = tern_get_node(tern_find_path(config, "bindings\0mice\0")); | |
940 if (mice) { | |
941 tern_node *buttonmaps[2] = {padbuttons, mousebuttons}; | |
942 tern_foreach(mice, process_mouse, buttonmaps); | |
758 } | 943 } |
759 tern_node * speed_nodes = tern_get_node(tern_find_path(config, "clocks\0speeds\0")); | 944 tern_node * speed_nodes = tern_get_node(tern_find_path(config, "clocks\0speeds\0")); |
760 speeds = malloc(sizeof(uint32_t)); | 945 speeds = malloc(sizeof(uint32_t)); |
761 speeds[0] = 100; | 946 speeds[0] = 100; |
762 process_speeds(speed_nodes, NULL); | 947 process_speeds(speed_nodes, NULL); |
788 } | 973 } |
789 if (joydpads[stick]) | 974 if (joydpads[stick]) |
790 { | 975 { |
791 map_bindings(ports, joydpads[stick]->bindings, 4); | 976 map_bindings(ports, joydpads[stick]->bindings, 4); |
792 } | 977 } |
978 } | |
979 for (int mouse = 0; mouse < MAX_MICE; mouse++) | |
980 { | |
981 if (mice[mouse].bind_type >= BIND_MOUSE1 && mice[mouse].bind_type <= BIND_MOUSE8) { | |
982 int num = mice[mouse].bind_type - BIND_MOUSE1; | |
983 for (int j = 0; j < 3; j++) | |
984 { | |
985 if (ports[j].device_type == IO_MOUSE && ports[j].device.mouse.mouse_num == num) | |
986 { | |
987 memset(ports[j].input, 0, sizeof(ports[j].input)); | |
988 mice[mouse].motion_port = ports + j; | |
989 break; | |
990 } | |
991 } | |
992 } | |
993 map_bindings(ports, mice[mouse].buttons, MAX_MOUSE_BUTTONS); | |
793 } | 994 } |
794 } | 995 } |
795 | 996 |
796 #define TH 0x40 | 997 #define TH 0x40 |
797 #define TR 0x20 | 998 #define TR 0x20 |
1012 input = 0x10; | 1213 input = 0x10; |
1013 } else { | 1214 } else { |
1014 input = 0; | 1215 input = 0; |
1015 } | 1216 } |
1016 } else { | 1217 } else { |
1017 int deltax = port->device.mouse.cur_x - port->device.mouse.last_read_x; | |
1018 int deltay = port->device.mouse.cur_y - port->device.mouse.last_read_y; | |
1019 switch (port->device.mouse.tr_counter) | 1218 switch (port->device.mouse.tr_counter) |
1020 { | 1219 { |
1021 case 0: | 1220 case 0: |
1022 input = 0xB; | 1221 input = 0xB; |
1023 break; | 1222 break; |
1025 case 2: | 1224 case 2: |
1026 input = 0xF; | 1225 input = 0xF; |
1027 break; | 1226 break; |
1028 case 3: | 1227 case 3: |
1029 input = 0; | 1228 input = 0; |
1030 if (deltay > 255 || deltay < -255) { | 1229 //it would be unfortunate if our event handler updated cur_x or cur_y in the middle |
1230 //of the mouse poll sequence, so we save the delta here | |
1231 port->device.mouse.delta_x = port->device.mouse.cur_x - port->device.mouse.last_read_x; | |
1232 port->device.mouse.delta_y = port->device.mouse.cur_y - port->device.mouse.last_read_y; | |
1233 if (port->device.mouse.delta_y > 255 || port->device.mouse.delta_y < -255) { | |
1031 input |= 8; | 1234 input |= 8; |
1032 } | 1235 } |
1033 if (deltax > 255 || deltax < -255) { | 1236 if (port->device.mouse.delta_x > 255 || port->device.mouse.delta_x < -255) { |
1034 input |= 4; | 1237 input |= 4; |
1035 } | 1238 } |
1036 if (deltay < 0) { | 1239 if (port->device.mouse.delta_y < 0) { |
1037 input |= 2; | 1240 input |= 2; |
1038 } | 1241 } |
1039 if (deltax < 0) { | 1242 if (port->device.mouse.delta_x < 0) { |
1040 input |= 1; | 1243 input |= 1; |
1041 } | 1244 } |
1042 break; | 1245 break; |
1043 case 4: | 1246 case 4: |
1044 input = port->input[0]; | 1247 input = port->input[0]; |
1045 break; | 1248 break; |
1046 case 5: | 1249 case 5: |
1047 input = abs(deltax) >> 4 & 0xF; | 1250 input = abs(port->device.mouse.delta_x) >> 4 & 0xF; |
1048 break; | 1251 break; |
1049 case 6: | 1252 case 6: |
1050 input = abs(deltax) & 0xF; | 1253 input = abs(port->device.mouse.delta_x) & 0xF; |
1051 break; | 1254 break; |
1052 case 7: | 1255 case 7: |
1053 input = abs(deltay) >> 4 & 0xF; | 1256 input = abs(port->device.mouse.delta_y) >> 4 & 0xF; |
1054 break; | 1257 break; |
1055 case 8: | 1258 case 8: |
1056 input = abs(deltay) & 0xF; | 1259 input = abs(port->device.mouse.delta_y) & 0xF; |
1057 //need to figure out when this actually happens | 1260 //need to figure out when this actually happens |
1058 port->device.mouse.last_read_x = port->device.mouse.cur_x; | 1261 port->device.mouse.last_read_x = port->device.mouse.cur_x; |
1059 port->device.mouse.last_read_y = port->device.mouse.cur_y; | 1262 port->device.mouse.last_read_y = port->device.mouse.cur_y; |
1060 break; | 1263 break; |
1061 default: | 1264 default: |