comparison io.c @ 803:236a184bf6f0

Merge
author Michael Pavone <pavone@retrodev.com>
date Sun, 26 Jul 2015 16:51:03 -0700
parents 41f73c76b978
children 9f149f0e98b7
comparison
equal deleted inserted replaced
802:6811f601008f 803:236a184bf6f0
1 /* 1 /*
2 Copyright 2013 Michael Pavone 2 Copyright 2013 Michael Pavone
3 This file is part of BlastEm. 3 This file is part of BlastEm.
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
5 */ 5 */
6 #ifndef _WIN32
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <sys/socket.h>
10 #include <sys/un.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <errno.h>
14 #endif
15 #include <string.h>
16 #include <stdlib.h>
17
6 #include "io.h" 18 #include "io.h"
7 #include "blastem.h" 19 #include "blastem.h"
8 #include "render.h" 20 #include "render.h"
9 21
22 const char * device_type_names[] = {
23 "3-button gamepad",
24 "6-button gamepad",
25 "Mega Mouse",
26 "Menacer",
27 "Justifier",
28 "Sega multi-tap",
29 "EA 4-way Play cable A",
30 "EA 4-way Play cable B",
31 "Sega Parallel Transfer Board",
32 "Generic Device",
33 "None"
34 };
35
10 enum { 36 enum {
11 BIND_NONE, 37 BIND_NONE,
38 BIND_UI,
12 BIND_GAMEPAD1, 39 BIND_GAMEPAD1,
13 BIND_GAMEPAD2, 40 BIND_GAMEPAD2,
14 BIND_UI 41 BIND_GAMEPAD3,
42 BIND_GAMEPAD4,
43 BIND_GAMEPAD5,
44 BIND_GAMEPAD6,
45 BIND_GAMEPAD7,
46 BIND_GAMEPAD8
15 }; 47 };
16 48
17 typedef enum { 49 typedef enum {
18 UI_DEBUG_MODE_INC, 50 UI_DEBUG_MODE_INC,
19 UI_DEBUG_PAL_INC, 51 UI_DEBUG_PAL_INC,
24 UI_PREV_SPEED, 56 UI_PREV_SPEED,
25 UI_EXIT 57 UI_EXIT
26 } ui_action; 58 } ui_action;
27 59
28 typedef struct { 60 typedef struct {
61 io_port *port;
29 uint8_t bind_type; 62 uint8_t bind_type;
30 uint8_t subtype_a; 63 uint8_t subtype_a;
31 uint8_t subtype_b; 64 uint8_t subtype_b;
32 uint8_t value; 65 uint8_t value;
33 } keybinding; 66 } keybinding;
115 #define BUTTON_C GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x20) 148 #define BUTTON_C GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x20)
116 149
117 void bind_gamepad(int keycode, int gamepadnum, int button) 150 void bind_gamepad(int keycode, int gamepadnum, int button)
118 { 151 {
119 152
120 if (gamepadnum < 1 || gamepadnum > 2) { 153 if (gamepadnum < 1 || gamepadnum > 8) {
121 return; 154 return;
122 } 155 }
123 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1; 156 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
124 bind_key(keycode, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF); 157 bind_key(keycode, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF);
125 } 158 }
126 159
127 void bind_button_gamepad(int joystick, int joybutton, int gamepadnum, int padbutton) 160 void bind_button_gamepad(int joystick, int joybutton, int gamepadnum, int padbutton)
128 { 161 {
129 if (gamepadnum < 1 || gamepadnum > 2) { 162 if (gamepadnum < 1 || gamepadnum > 8) {
130 return; 163 return;
131 } 164 }
132 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1; 165 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
133 bind_button(joystick, joybutton, bind_type, padbutton >> 12, padbutton >> 8 & 0xF, padbutton & 0xFF); 166 bind_button(joystick, joybutton, bind_type, padbutton >> 12, padbutton >> 8 & 0xF, padbutton & 0xFF);
134 } 167 }
135 168
136 void bind_dpad_gamepad(int joystick, int dpad, uint8_t direction, int gamepadnum, int button) 169 void bind_dpad_gamepad(int joystick, int dpad, uint8_t direction, int gamepadnum, int button)
137 { 170 {
138 if (gamepadnum < 1 || gamepadnum > 2) { 171 if (gamepadnum < 1 || gamepadnum > 8) {
139 return; 172 return;
140 } 173 }
141 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1; 174 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
142 bind_dpad(joystick, dpad, direction, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF); 175 bind_dpad(joystick, dpad, direction, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF);
143 } 176 }
157 bind_dpad(joystick, dpad, direction, BIND_UI, action, 0, param); 190 bind_dpad(joystick, dpad, direction, BIND_UI, action, 0, param);
158 } 191 }
159 192
160 void handle_binding_down(keybinding * binding) 193 void handle_binding_down(keybinding * binding)
161 { 194 {
162 switch(binding->bind_type) 195 if (binding->bind_type >= BIND_GAMEPAD1)
163 { 196 {
164 case BIND_GAMEPAD1: 197 if (binding->subtype_a <= GAMEPAD_EXTRA && binding->port) {
165 case BIND_GAMEPAD2: 198 binding->port->input[binding->subtype_a] |= binding->value;
166 if (binding->subtype_a <= GAMEPAD_EXTRA) { 199 }
167 genesis->ports[binding->bind_type - BIND_GAMEPAD1].input[binding->subtype_a] |= binding->value; 200 if (binding->subtype_b <= GAMEPAD_EXTRA && binding->port) {
168 } 201 binding->port->input[binding->subtype_b] |= binding->value;
169 if (binding->subtype_b <= GAMEPAD_EXTRA) { 202 }
170 genesis->ports[binding->bind_type - BIND_GAMEPAD1].input[binding->subtype_b] |= binding->value;
171 }
172 break;
173 } 203 }
174 } 204 }
175 205
176 void handle_keydown(int keycode) 206 void handle_keydown(int keycode)
177 { 207 {
204 { 234 {
205 switch(binding->bind_type) 235 switch(binding->bind_type)
206 { 236 {
207 case BIND_GAMEPAD1: 237 case BIND_GAMEPAD1:
208 case BIND_GAMEPAD2: 238 case BIND_GAMEPAD2:
209 if (binding->subtype_a <= GAMEPAD_EXTRA) { 239 if (binding->subtype_a <= GAMEPAD_EXTRA && binding->port) {
210 genesis->ports[binding->bind_type - BIND_GAMEPAD1].input[binding->subtype_a] &= ~binding->value; 240 binding->port->input[binding->subtype_a] &= ~binding->value;
211 } 241 }
212 if (binding->subtype_b <= GAMEPAD_EXTRA) { 242 if (binding->subtype_b <= GAMEPAD_EXTRA && binding->port) {
213 genesis->ports[binding->bind_type - BIND_GAMEPAD1].input[binding->subtype_b] &= ~binding->value; 243 binding->port->input[binding->subtype_b] &= ~binding->value;
214 } 244 }
215 break; 245 break;
216 case BIND_UI: 246 case BIND_UI:
217 switch (binding->subtype_a) 247 switch (binding->subtype_a)
218 { 248 {
219 case UI_DEBUG_MODE_INC: 249 case UI_DEBUG_MODE_INC:
220 ui_debug_mode++; 250 ui_debug_mode++;
221 if (ui_debug_mode == 4) { 251 if (ui_debug_mode == 7) {
222 ui_debug_mode = 0; 252 ui_debug_mode = 0;
223 } 253 }
224 genesis->vdp->debug = ui_debug_mode; 254 genesis->vdp->debug = ui_debug_mode;
225 break; 255 break;
226 case UI_DEBUG_PAL_INC: 256 case UI_DEBUG_PAL_INC:
227 ui_debug_pal++; 257 ui_debug_pal++;
228 if (ui_debug_pal == 4) { 258 if (ui_debug_pal == 4) {
229 ui_debug_pal = 0; 259 ui_debug_pal = 0;
230 } 260 }
231 render_debug_pal(ui_debug_pal); 261 genesis->vdp->debug_pal = ui_debug_pal;
232 break; 262 break;
233 case UI_ENTER_DEBUGGER: 263 case UI_ENTER_DEBUGGER:
234 break_on_sync = 1; 264 break_on_sync = 1;
235 break; 265 break;
236 case UI_SAVE_STATE: 266 case UI_SAVE_STATE:
308 } 338 }
309 339
310 int parse_binding_target(char * target, tern_node * padbuttons, int * ui_out, int * padnum_out, int * padbutton_out) 340 int parse_binding_target(char * target, tern_node * padbuttons, int * ui_out, int * padnum_out, int * padbutton_out)
311 { 341 {
312 int gpadslen = strlen("gamepads."); 342 int gpadslen = strlen("gamepads.");
313 if (!memcmp(target, "gamepads.", gpadslen)) { 343 if (!strncmp(target, "gamepads.", gpadslen)) {
314 if (target[gpadslen] >= '1' && target[gpadslen] <= '8') { 344 if (target[gpadslen] >= '1' && target[gpadslen] <= '8') {
315 int padnum = target[gpadslen] - '0'; 345 int padnum = target[gpadslen] - '0';
316 int button = tern_find_int(padbuttons, target + gpadslen + 1, 0); 346 int button = tern_find_int(padbuttons, target + gpadslen + 1, 0);
317 if (button) { 347 if (button) {
318 *padnum_out = padnum; 348 *padnum_out = padnum;
326 } 356 }
327 } 357 }
328 } else { 358 } else {
329 fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]); 359 fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]);
330 } 360 }
331 } else if(!memcmp(target, "ui.", strlen("ui."))) { 361 } else if(!strncmp(target, "ui.", strlen("ui."))) {
332 *padbutton_out = 0; 362 *padbutton_out = 0;
333 if (!strcmp(target + 3, "vdp_debug_mode")) { 363 if (!strcmp(target + 3, "vdp_debug_mode")) {
334 *ui_out = UI_DEBUG_MODE_INC; 364 *ui_out = UI_DEBUG_MODE_INC;
335 } else if(!strcmp(target + 3, "vdp_debug_pal")) { 365 } else if(!strcmp(target + 3, "vdp_debug_pal")) {
336 *ui_out = UI_DEBUG_PAL_INC; 366 *ui_out = UI_DEBUG_PAL_INC;
337 } else if(!strcmp(target + 3, "enter_debugger")) { 367 } else if(!strcmp(target + 3, "enter_debugger")) {
338 *ui_out = UI_ENTER_DEBUGGER; 368 *ui_out = UI_ENTER_DEBUGGER;
339 } else if(!strcmp(target + 3, "save_state")) { 369 } else if(!strcmp(target + 3, "save_state")) {
340 *ui_out = UI_SAVE_STATE; 370 *ui_out = UI_SAVE_STATE;
341 } else if(!memcmp(target + 3, "set_speed.", strlen("set_speed."))) { 371 } else if(!strncmp(target + 3, "set_speed.", strlen("set_speed."))) {
342 *ui_out = UI_SET_SPEED; 372 *ui_out = UI_SET_SPEED;
343 *padbutton_out = atoi(target + 3 + strlen("set_speed.")); 373 *padbutton_out = atoi(target + 3 + strlen("set_speed."));
344 } else if(!strcmp(target + 3, "next_speed")) { 374 } else if(!strcmp(target + 3, "next_speed")) {
345 *ui_out = UI_NEXT_SPEED; 375 *ui_out = UI_NEXT_SPEED;
346 } else if(!strcmp(target + 3, "prev_speed")) { 376 } else if(!strcmp(target + 3, "prev_speed")) {
445 if (curstr && len) { 475 if (curstr && len) {
446 free(curstr); 476 free(curstr);
447 } 477 }
448 } 478 }
449 479
450 void set_keybindings() 480 void process_device(char * device_type, io_port * port)
481 {
482 port->device_type = IO_NONE;
483 if (!device_type)
484 {
485 return;
486 }
487
488 const int gamepad_len = strlen("gamepad");
489 if (!memcmp(device_type, "gamepad", gamepad_len))
490 {
491 if (
492 (device_type[gamepad_len] != '3' && device_type[gamepad_len] != '6')
493 || device_type[gamepad_len+1] != '.' || device_type[gamepad_len+2] < '1'
494 || device_type[gamepad_len+2] > '8' || device_type[gamepad_len+3] != 0
495 )
496 {
497 fprintf(stderr, "%s is not a valid gamepad type\n", device_type);
498 } else if (device_type[gamepad_len] == '3')
499 {
500 port->device_type = IO_GAMEPAD3;
501 } else {
502 port->device_type = IO_GAMEPAD6;
503 }
504 port->device.pad.gamepad_num = device_type[gamepad_len+2] - '1';
505 } else if(!strcmp(device_type, "sega_parallel")) {
506 port->device_type = IO_SEGA_PARALLEL;
507 port->device.stream.data_fd = -1;
508 port->device.stream.listen_fd = -1;
509 } else if(!strcmp(device_type, "generic")) {
510 port->device_type = IO_GENERIC;
511 port->device.stream.data_fd = -1;
512 port->device.stream.listen_fd = -1;
513 }
514 }
515
516 char * io_name(int i)
517 {
518 switch (i)
519 {
520 case 0:
521 return "1";
522 case 1:
523 return "2";
524 case 2:
525 return "EXT";
526 default:
527 return "invalid";
528 }
529 }
530
531 static char * sockfile_name;
532 static void cleanup_sockfile()
533 {
534 unlink(sockfile_name);
535 }
536
537 void setup_io_devices(tern_node * config, io_port * ports)
538 {
539 tern_node *io_nodes = tern_get_node(tern_find_path(config, "io\0devices\0"));
540 char * io_1 = tern_find_ptr(io_nodes, "1");
541 char * io_2 = tern_find_ptr(io_nodes, "2");
542 char * io_ext = tern_find_ptr(io_nodes, "ext");
543
544 process_device(io_1, ports);
545 process_device(io_2, ports+1);
546 process_device(io_ext, ports+2);
547
548 for (int i = 0; i < 3; i++)
549 {
550 #ifndef _WIN32
551 if (ports[i].device_type == IO_SEGA_PARALLEL)
552 {
553 char *pipe_name = tern_find_path(config, "io\0parallel_pipe\0").ptrval;
554 if (!pipe_name)
555 {
556 fprintf(stderr, "IO port %s is configured to use the sega parallel board, but no paralell_pipe is set!\n", io_name(i));
557 ports[i].device_type = IO_NONE;
558 } else {
559 printf("IO port: %s connected to device '%s' with pipe name: %s\n", io_name(i), device_type_names[ports[i].device_type], pipe_name);
560 if (!strcmp("stdin", pipe_name))
561 {
562 ports[i].device.stream.data_fd = STDIN_FILENO;
563 } else {
564 if (mkfifo(pipe_name, 0666) && errno != EEXIST)
565 {
566 fprintf(stderr, "Failed to create fifo %s for Sega parallel board emulation: %d %s\n", pipe_name, errno, strerror(errno));
567 ports[i].device_type = IO_NONE;
568 } else {
569 ports[i].device.stream.data_fd = open(pipe_name, O_NONBLOCK | O_RDONLY);
570 if (ports[i].device.stream.data_fd == -1)
571 {
572 fprintf(stderr, "Failed to open fifo %s for Sega parallel board emulation: %d %s\n", pipe_name, errno, strerror(errno));
573 ports[i].device_type = IO_NONE;
574 }
575 }
576 }
577 }
578 } else if (ports[i].device_type == IO_GENERIC) {
579 char *sock_name = tern_find_path(config, "io\0socket\0").ptrval;
580 if (!sock_name)
581 {
582 fprintf(stderr, "IO port %s is configured to use generic IO, but no socket is set!\n", io_name(i));
583 ports[i].device_type = IO_NONE;
584 } else {
585 printf("IO port: %s connected to device '%s' with socket name: %s\n", io_name(i), device_type_names[ports[i].device_type], sock_name);
586 ports[i].device.stream.data_fd = -1;
587 ports[i].device.stream.listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
588 size_t pathlen = strlen(sock_name);
589 size_t addrlen = offsetof(struct sockaddr_un, sun_path) + pathlen + 1;
590 struct sockaddr_un *saddr = malloc(addrlen);
591 saddr->sun_family = AF_UNIX;
592 memcpy(saddr->sun_path, sock_name, pathlen+1);
593 if (bind(ports[i].device.stream.listen_fd, (struct sockaddr *)saddr, addrlen))
594 {
595 fprintf(stderr, "Failed to bind socket for IO Port %s to path %s: %d %s\n", io_name(i), sock_name, errno, strerror(errno));
596 goto cleanup_sock;
597 }
598 if (listen(ports[i].device.stream.listen_fd, 1))
599 {
600 fprintf(stderr, "Failed to listen on socket for IO Port %s: %d %s\n", io_name(i), errno, strerror(errno));
601 goto cleanup_sockfile;
602 }
603 sockfile_name = sock_name;
604 atexit(cleanup_sockfile);
605 continue;
606 cleanup_sockfile:
607 unlink(sock_name);
608 cleanup_sock:
609 close(ports[i].device.stream.listen_fd);
610 ports[i].device_type = IO_NONE;
611 }
612 } else
613 #endif
614 if (ports[i].device_type == IO_GAMEPAD3 || ports[i].device_type == IO_GAMEPAD6) {
615 printf("IO port %s connected to gamepad #%d with type '%s'\n", io_name(i), ports[i].device.pad.gamepad_num + 1, device_type_names[ports[i].device_type]);
616 } else {
617 printf("IO port %s connected to device '%s'\n", io_name(i), device_type_names[ports[i].device_type]);
618 }
619 }
620 }
621
622 void map_bindings(io_port *ports, keybinding *bindings, int numbindings)
623 {
624 for (int i = 0; i < numbindings; i++)
625 {
626 if (bindings[i].bind_type >= BIND_GAMEPAD1)
627 {
628 int num = bindings[i].bind_type - BIND_GAMEPAD1;
629 for (int j = 0; j < 3; j++)
630 {
631 if ((ports[j].device_type == IO_GAMEPAD3
632 || ports[j].device_type ==IO_GAMEPAD6)
633 && ports[j].device.pad.gamepad_num == num
634 )
635 {
636 bindings[i].port = ports + j;
637 break;
638 }
639 }
640 }
641 }
642 }
643
644 void set_keybindings(io_port *ports)
451 { 645 {
452 tern_node * special = tern_insert_int(NULL, "up", RENDERKEY_UP); 646 tern_node * special = tern_insert_int(NULL, "up", RENDERKEY_UP);
453 special = tern_insert_int(special, "down", RENDERKEY_DOWN); 647 special = tern_insert_int(special, "down", RENDERKEY_DOWN);
454 special = tern_insert_int(special, "left", RENDERKEY_LEFT); 648 special = tern_insert_int(special, "left", RENDERKEY_LEFT);
455 special = tern_insert_int(special, "right", RENDERKEY_RIGHT); 649 special = tern_insert_int(special, "right", RENDERKEY_RIGHT);
469 padbuttons = tern_insert_int(padbuttons, ".y", BUTTON_Y); 663 padbuttons = tern_insert_int(padbuttons, ".y", BUTTON_Y);
470 padbuttons = tern_insert_int(padbuttons, ".z", BUTTON_Z); 664 padbuttons = tern_insert_int(padbuttons, ".z", BUTTON_Z);
471 padbuttons = tern_insert_int(padbuttons, ".start", BUTTON_START); 665 padbuttons = tern_insert_int(padbuttons, ".start", BUTTON_START);
472 padbuttons = tern_insert_int(padbuttons, ".mode", BUTTON_MODE); 666 padbuttons = tern_insert_int(padbuttons, ".mode", BUTTON_MODE);
473 667
474 tern_node * keys = tern_find_prefix(config, "bindingskeys"); 668 tern_node * keys = tern_get_node(tern_find_path(config, "bindings\0keys\0"));
475 process_keys(keys, special, padbuttons, NULL); 669 process_keys(keys, special, padbuttons, NULL);
476 char prefix[] = "bindingspads00"; 670 char numstr[] = "00";
477 for (int i = 0; i < 100 && i < render_num_joysticks(); i++) 671 tern_node * pads = tern_get_node(tern_find_path(config, "bindings\0pads\0"));
478 { 672 if (pads) {
479 if (i < 10) { 673 for (int i = 0; i < 100 && i < render_num_joysticks(); i++)
480 prefix[strlen("bindingspads")] = i + '0'; 674 {
481 prefix[strlen("bindingspads")+1] = 0; 675
482 } else { 676 if (i < 10) {
483 prefix[strlen("bindingspads")] = i/10 + '0'; 677 numstr[0] = i + '0';
484 prefix[strlen("bindingspads")+1] = i%10 + '0'; 678 numstr[1] = 0;
485 } 679 } else {
486 tern_node * pad = tern_find_prefix(config, prefix); 680 numstr[0] = i/10 + '0';
487 if (pad) { 681 numstr[1] = i%10 + '0';
488 char dprefix[] = "dpads0"; 682 }
489 for (int dpad = 0; dpad < 10 && dpad < render_joystick_num_hats(i); dpad++) 683 tern_node * pad = tern_find_ptr(pads, numstr);
490 { 684 if (pad) {
491 dprefix[strlen("dpads")] = dpad + '0'; 685 tern_node * dpad_node = tern_find_ptr(pad, "dpads");
492 tern_node * pad_dpad = tern_find_prefix(pad, dprefix); 686 if (dpad_node) {
493 char * dirs[] = {"up", "down", "left", "right"}; 687 for (int dpad = 0; dpad < 10 && dpad < render_joystick_num_hats(i); dpad++)
494 int dirnums[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT}; 688 {
495 for (int dir = 0; dir < sizeof(dirs)/sizeof(dirs[0]); dir++) { 689 numstr[0] = dpad + '0';
496 char * target = tern_find_ptr(pad_dpad, dirs[dir]); 690 numstr[1] = 0;
497 if (target) { 691 tern_node * pad_dpad = tern_find_ptr(dpad_node, numstr);
498 int ui_func, padnum, button; 692 char * dirs[] = {"up", "down", "left", "right"};
499 int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button); 693 int dirnums[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT};
500 if (bindtype == 1) { 694 for (int dir = 0; dir < sizeof(dirs)/sizeof(dirs[0]); dir++) {
501 bind_dpad_gamepad(i, dpad, dirnums[dir], padnum, button); 695 char * target = tern_find_ptr(pad_dpad, dirs[dir]);
502 } else if (bindtype == 2) { 696 if (target) {
503 bind_dpad_ui(i, dpad, dirnums[dir], ui_func, button); 697 int ui_func, padnum, button;
698 int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button);
699 if (bindtype == 1) {
700 bind_dpad_gamepad(i, dpad, dirnums[dir], padnum, button);
701 } else if (bindtype == 2) {
702 bind_dpad_ui(i, dpad, dirnums[dir], ui_func, button);
703 }
704 }
504 } 705 }
505 } 706 }
506 } 707 }
507 } 708 tern_node *button_node = tern_find_ptr(pad, "buttons");
508 char bprefix[] = "buttons00"; 709 if (button_node) {
509 for (int but = 0; but < 100 && but < render_joystick_num_buttons(i); but++) 710 for (int but = 0; but < 100 && but < render_joystick_num_buttons(i); but++)
510 { 711 {
511 if (but < 10) { 712 if (but < 10) {
512 bprefix[strlen("buttons")] = but + '0'; 713 numstr[0] = but + '0';
513 bprefix[strlen("buttons")+1] = 0; 714 numstr[1] = 0;
514 } else { 715 } else {
515 bprefix[strlen("buttons")] = but/10 + '0'; 716 numstr[0] = but/10 + '0';
516 bprefix[strlen("buttons")+1] = but%10 + '0'; 717 numstr[1] = but%10 + '0';
517 } 718 }
518 char * target = tern_find_ptr(pad, bprefix); 719 char * target = tern_find_ptr(button_node, numstr);
519 if (target) { 720 if (target) {
520 int ui_func, padnum, button; 721 int ui_func, padnum, button;
521 int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button); 722 int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button);
522 if (bindtype == 1) { 723 if (bindtype == 1) {
523 bind_button_gamepad(i, but, padnum, button); 724 bind_button_gamepad(i, but, padnum, button);
524 } else if (bindtype == 2) { 725 } else if (bindtype == 2) {
525 bind_button_ui(i, but, ui_func, button); 726 bind_button_ui(i, but, ui_func, button);
727 }
728 }
526 } 729 }
527 } 730 }
528 } 731 }
529 } 732 }
530 } 733 }
531 tern_node * speed_nodes = tern_find_prefix(config, "clocksspeeds"); 734 tern_node * speed_nodes = tern_get_node(tern_find_path(config, "clocks\0speeds\0"));
532 speeds = malloc(sizeof(uint32_t)); 735 speeds = malloc(sizeof(uint32_t));
533 speeds[0] = 100; 736 speeds[0] = 100;
534 process_speeds(speed_nodes, NULL); 737 process_speeds(speed_nodes, NULL);
535 for (int i = 0; i < num_speeds; i++) { 738 for (int i = 0; i < num_speeds; i++)
739 {
536 if (!speeds[i]) { 740 if (!speeds[i]) {
537 fprintf(stderr, "Speed index %d was not set to a valid percentage!", i); 741 fprintf(stderr, "Speed index %d was not set to a valid percentage!", i);
538 speeds[i] = 100; 742 speeds[i] = 100;
539 } 743 }
540 } 744 }
745 for (int bucket = 0; bucket < 256; bucket++)
746 {
747 if (bindings[bucket])
748 {
749 map_bindings(ports, bindings[bucket], 256);
750 }
751 }
752 for (int stick = 0; stick < MAX_JOYSTICKS; stick++)
753 {
754 if (joybindings[stick])
755 {
756 int numbuttons = render_joystick_num_buttons(stick);
757 map_bindings(ports, joybindings[stick], render_joystick_num_buttons(stick));
758 }
759 if (joydpads[stick])
760 {
761 map_bindings(ports, joydpads[stick]->bindings, 4);
762 }
763 }
541 } 764 }
542 765
543 #define TH 0x40 766 #define TH 0x40
544 #define TH_TIMEOUT 8000 767 #define TH_TIMEOUT 56000
545 768
546 void io_adjust_cycles(io_port * pad, uint32_t current_cycle, uint32_t deduction) 769 void io_adjust_cycles(io_port * port, uint32_t current_cycle, uint32_t deduction)
547 { 770 {
548 /*uint8_t control = pad->control | 0x80; 771 /*uint8_t control = pad->control | 0x80;
549 uint8_t th = control & pad->output; 772 uint8_t th = control & pad->output;
550 if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) { 773 if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) {
551 printf("adjust_cycles | control: %X, TH: %X, GAMEPAD_TH0: %X, GAMEPAD_TH1: %X, TH Counter: %d, Timeout: %d, Cycle: %d\n", control, th, pad->input[GAMEPAD_TH0], pad->input[GAMEPAD_TH1], pad->th_counter,pad->timeout_cycle, current_cycle); 774 printf("adjust_cycles | control: %X, TH: %X, GAMEPAD_TH0: %X, GAMEPAD_TH1: %X, TH Counter: %d, Timeout: %d, Cycle: %d\n", control, th, pad->input[GAMEPAD_TH0], pad->input[GAMEPAD_TH1], pad->th_counter,pad->timeout_cycle, current_cycle);
552 }*/ 775 }*/
553 if (current_cycle >= pad->timeout_cycle) { 776 if (port->device_type == IO_GAMEPAD6)
554 pad->th_counter = 0; 777 {
555 } else { 778 if (current_cycle >= port->device.pad.timeout_cycle)
556 pad->timeout_cycle -= deduction; 779 {
557 } 780 port->device.pad.th_counter = 0;
558 } 781 } else {
559 782 port->device.pad.timeout_cycle -= deduction;
560 void io_data_write(io_port * pad, uint8_t value, uint32_t current_cycle) 783 }
561 { 784 }
562 if (pad->control & TH) { 785 }
563 //check if TH has changed 786
564 if ((pad->output & TH) ^ (value & TH)) { 787 #ifndef _WIN32
565 if (current_cycle >= pad->timeout_cycle) { 788 static void wait_for_connection(io_port * port)
566 pad->th_counter = 0; 789 {
567 } 790 if (port->device.stream.data_fd == -1)
568 if (!(value & TH)) { 791 {
569 pad->th_counter++; 792 puts("Waiting for socket connection...");
570 } 793 port->device.stream.data_fd = accept(port->device.stream.listen_fd, NULL, NULL);
571 pad->timeout_cycle = current_cycle + TH_TIMEOUT; 794 fcntl(port->device.stream.data_fd, F_SETFL, O_NONBLOCK | O_RDWR);
572 } 795 }
573 } 796 }
574 pad->output = value; 797
575 } 798 static void service_pipe(io_port * port)
576 799 {
577 uint8_t io_data_read(io_port * pad, uint32_t current_cycle) 800 uint8_t value;
578 { 801 int numRead = read(port->device.stream.data_fd, &value, sizeof(value));
579 uint8_t control = pad->control | 0x80; 802 if (numRead > 0)
580 uint8_t th = control & pad->output; 803 {
804 port->input[IO_TH0] = (value & 0xF) | 0x10;
805 port->input[IO_TH1] = (value >> 4) | 0x10;
806 } else if(numRead == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
807 fprintf(stderr, "Error reading pipe for IO port: %d %s\n", errno, strerror(errno));
808 }
809 }
810
811 static void service_socket(io_port *port)
812 {
813 uint8_t buf[32];
814 uint8_t blocking = 0;
815 int numRead = 0;
816 while (numRead <= 0)
817 {
818 numRead = recv(port->device.stream.data_fd, buf, sizeof(buf), 0);
819 if (numRead > 0)
820 {
821 port->input[IO_TH0] = buf[numRead-1];
822 if (port->input[IO_STATE] == IO_READ_PENDING)
823 {
824 port->input[IO_STATE] = IO_READ;
825 if (blocking)
826 {
827 //pending read satisfied, back to non-blocking mode
828 fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR | O_NONBLOCK);
829 }
830 } else if (port->input[IO_STATE] == IO_WRITTEN) {
831 port->input[IO_STATE] = IO_READ;
832 }
833 } else if (numRead == 0) {
834 port->device.stream.data_fd = -1;
835 wait_for_connection(port);
836 } else if (errno != EAGAIN && errno != EWOULDBLOCK) {
837 fprintf(stderr, "Error reading from socket for IO port: %d %s\n", errno, strerror(errno));
838 close(port->device.stream.data_fd);
839 wait_for_connection(port);
840 } else if (port->input[IO_STATE] == IO_READ_PENDING) {
841 //clear the nonblocking flag so the next read will block
842 if (!blocking)
843 {
844 fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR);
845 blocking = 1;
846 }
847 } else {
848 //no new data, but that's ok
849 break;
850 }
851 }
852
853 if (port->input[IO_STATE] == IO_WRITE_PENDING)
854 {
855 uint8_t value = port->output & port->control;
856 int written = 0;
857 blocking = 0;
858 while (written <= 0)
859 {
860 send(port->device.stream.data_fd, &value, sizeof(value), 0);
861 if (written > 0)
862 {
863 port->input[IO_STATE] = IO_WRITTEN;
864 if (blocking)
865 {
866 //pending write satisfied, back to non-blocking mode
867 fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR | O_NONBLOCK);
868 }
869 } else if (written == 0) {
870 port->device.stream.data_fd = -1;
871 wait_for_connection(port);
872 } else if (errno != EAGAIN && errno != EWOULDBLOCK) {
873 fprintf(stderr, "Error writing to socket for IO port: %d %s\n", errno, strerror(errno));
874 close(port->device.stream.data_fd);
875 wait_for_connection(port);
876 } else {
877 //clear the nonblocking flag so the next write will block
878 if (!blocking)
879 {
880 fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR);
881 blocking = 1;
882 }
883 }
884 }
885 }
886 }
887 #endif
888
889 void io_data_write(io_port * port, uint8_t value, uint32_t current_cycle)
890 {
891 switch (port->device_type)
892 {
893 case IO_GAMEPAD6:
894 if (port->control & TH) {
895 //check if TH has changed
896 if ((port->output & TH) ^ (value & TH)) {
897 if (current_cycle >= port->device.pad.timeout_cycle) {
898 port->device.pad.th_counter = 0;
899 }
900 if (!(value & TH)) {
901 port->device.pad.th_counter++;
902 }
903 port->device.pad.timeout_cycle = current_cycle + TH_TIMEOUT;
904 }
905 }
906 port->output = value;
907 break;
908 #ifndef _WIN32
909 case IO_GENERIC:
910 wait_for_connection(port);
911 port->input[IO_STATE] = IO_WRITE_PENDING;
912 port->output = value;
913 service_socket(port);
914 break;
915 #endif
916 default:
917 port->output = value;
918 }
919
920 }
921
922 uint8_t io_data_read(io_port * port, uint32_t current_cycle)
923 {
924 uint8_t control = port->control | 0x80;
925 uint8_t th = control & port->output & 0x40;
581 uint8_t input; 926 uint8_t input;
582 if (current_cycle >= pad->timeout_cycle) { 927 switch (port->device_type)
583 pad->th_counter = 0; 928 {
584 } 929 case IO_GAMEPAD3:
585 /*if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) { 930 {
586 printf("io_data_read | control: %X, TH: %X, GAMEPAD_TH0: %X, GAMEPAD_TH1: %X, TH Counter: %d, Timeout: %d, Cycle: %d\n", control, th, pad->input[GAMEPAD_TH0], pad->input[GAMEPAD_TH1], pad->th_counter,pad->timeout_cycle, context->current_cycle); 931 input = port->input[th ? GAMEPAD_TH1 : GAMEPAD_TH0];
587 }*/ 932 break;
588 if (th) { 933 }
589 if (pad->th_counter == 3) { 934 case IO_GAMEPAD6:
590 input = pad->input[GAMEPAD_EXTRA]; 935 {
936 if (current_cycle >= port->device.pad.timeout_cycle) {
937 port->device.pad.th_counter = 0;
938 }
939 /*if (port->input[GAMEPAD_TH0] || port->input[GAMEPAD_TH1]) {
940 printf("io_data_read | control: %X, TH: %X, GAMEPAD_TH0: %X, GAMEPAD_TH1: %X, TH Counter: %d, Timeout: %d, Cycle: %d\n", control, th, port->input[GAMEPAD_TH0], port->input[GAMEPAD_TH1], port->th_counter,port->timeout_cycle, context->current_cycle);
941 }*/
942 if (th) {
943 if (port->device.pad.th_counter == 3) {
944 input = port->input[GAMEPAD_EXTRA];
945 } else {
946 input = port->input[GAMEPAD_TH1];
947 }
591 } else { 948 } else {
592 input = pad->input[GAMEPAD_TH1]; 949 if (port->device.pad.th_counter == 3) {
593 } 950 input = port->input[GAMEPAD_TH0] | 0xF;
594 } else { 951 } else if(port->device.pad.th_counter == 4) {
595 if (pad->th_counter == 3) { 952 input = port->input[GAMEPAD_TH0] & 0x30;
596 input = pad->input[GAMEPAD_TH0] | 0xF; 953 } else {
597 } else if(pad->th_counter == 4) { 954 input = port->input[GAMEPAD_TH0] | 0xC;
598 input = pad->input[GAMEPAD_TH0] & 0x30; 955 }
599 } else { 956 }
600 input = pad->input[GAMEPAD_TH0] | 0xC; 957 break;
601 } 958 }
602 } 959 #ifndef _WIN32
603 uint8_t value = ((~input) & (~control)) | (pad->output & control); 960 case IO_SEGA_PARALLEL:
604 /*if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) { 961 if (!th)
962 {
963 service_pipe(port);
964 }
965 input = ~port->input[th ? IO_TH1 : IO_TH0];
966 break;
967 case IO_GENERIC:
968 if (port->input[IO_TH0] & 0x80 && port->input[IO_STATE] == IO_WRITTEN)
969 {
970 //device requested a blocking read after writes
971 port->input[IO_STATE] = IO_READ_PENDING;
972 }
973 service_socket(port);
974 input = ~port->input[IO_TH0];
975 break;
976 #endif
977 default:
978 input = 0;
979 break;
980 }
981 uint8_t value = ((~input) & (~control)) | (port->output & control);
982 /*if (port->input[GAMEPAD_TH0] || port->input[GAMEPAD_TH1]) {
605 printf ("value: %X\n", value); 983 printf ("value: %X\n", value);
606 }*/ 984 }*/
607 return value; 985 return value;
608 } 986 }
609 987