comparison io.c @ 645:d77c79cec800

Initial support for configurable IO, custom IO and sega transfer board emulation
author Michael Pavone <pavone@retrodev.com>
date Wed, 03 Dec 2014 09:32:32 -0800
parents 7b0df1aaf384
children 7497334bb548
comparison
equal deleted inserted replaced
644:2d7e84ae818c 645:d77c79cec800
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 #include <unistd.h>
7 #include <fcntl.h>
8 #include <sys/socket.h>
9 #include <sys/un.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <errno.h>
13 #include <string.h>
14
6 #include "io.h" 15 #include "io.h"
7 #include "blastem.h" 16 #include "blastem.h"
8 #include "render.h" 17 #include "render.h"
9 18
19 const char * device_type_names[] = {
20 "3-button gamepad",
21 "6-button gamepad",
22 "Mega Mouse",
23 "Menacer",
24 "Justifier",
25 "Sega multi-tap",
26 "EA 4-way Play cable A",
27 "EA 4-way Play cable B",
28 "Sega Parallel Transfer Board",
29 "Generic Device",
30 "None"
31 };
32
10 enum { 33 enum {
11 BIND_NONE, 34 BIND_NONE,
35 BIND_UI,
12 BIND_GAMEPAD1, 36 BIND_GAMEPAD1,
13 BIND_GAMEPAD2, 37 BIND_GAMEPAD2,
14 BIND_UI 38 BIND_GAMEPAD3,
39 BIND_GAMEPAD4,
40 BIND_GAMEPAD5,
41 BIND_GAMEPAD6,
42 BIND_GAMEPAD7,
43 BIND_GAMEPAD8
15 }; 44 };
16 45
17 typedef enum { 46 typedef enum {
18 UI_DEBUG_MODE_INC, 47 UI_DEBUG_MODE_INC,
19 UI_DEBUG_PAL_INC, 48 UI_DEBUG_PAL_INC,
24 UI_PREV_SPEED, 53 UI_PREV_SPEED,
25 UI_EXIT 54 UI_EXIT
26 } ui_action; 55 } ui_action;
27 56
28 typedef struct { 57 typedef struct {
58 io_port *port;
29 uint8_t bind_type; 59 uint8_t bind_type;
30 uint8_t subtype_a; 60 uint8_t subtype_a;
31 uint8_t subtype_b; 61 uint8_t subtype_b;
32 uint8_t value; 62 uint8_t value;
33 } keybinding; 63 } keybinding;
115 #define BUTTON_C GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x20) 145 #define BUTTON_C GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x20)
116 146
117 void bind_gamepad(int keycode, int gamepadnum, int button) 147 void bind_gamepad(int keycode, int gamepadnum, int button)
118 { 148 {
119 149
120 if (gamepadnum < 1 || gamepadnum > 2) { 150 if (gamepadnum < 1 || gamepadnum > 8) {
121 return; 151 return;
122 } 152 }
123 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1; 153 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
124 bind_key(keycode, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF); 154 bind_key(keycode, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF);
125 } 155 }
126 156
127 void bind_button_gamepad(int joystick, int joybutton, int gamepadnum, int padbutton) 157 void bind_button_gamepad(int joystick, int joybutton, int gamepadnum, int padbutton)
128 { 158 {
129 if (gamepadnum < 1 || gamepadnum > 2) { 159 if (gamepadnum < 1 || gamepadnum > 8) {
130 return; 160 return;
131 } 161 }
132 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1; 162 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
133 bind_button(joystick, joybutton, bind_type, padbutton >> 12, padbutton >> 8 & 0xF, padbutton & 0xFF); 163 bind_button(joystick, joybutton, bind_type, padbutton >> 12, padbutton >> 8 & 0xF, padbutton & 0xFF);
134 } 164 }
135 165
136 void bind_dpad_gamepad(int joystick, int dpad, uint8_t direction, int gamepadnum, int button) 166 void bind_dpad_gamepad(int joystick, int dpad, uint8_t direction, int gamepadnum, int button)
137 { 167 {
138 if (gamepadnum < 1 || gamepadnum > 2) { 168 if (gamepadnum < 1 || gamepadnum > 8) {
139 return; 169 return;
140 } 170 }
141 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1; 171 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
142 bind_dpad(joystick, dpad, direction, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF); 172 bind_dpad(joystick, dpad, direction, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF);
143 } 173 }
157 bind_dpad(joystick, dpad, direction, BIND_UI, action, 0, param); 187 bind_dpad(joystick, dpad, direction, BIND_UI, action, 0, param);
158 } 188 }
159 189
160 void handle_binding_down(keybinding * binding) 190 void handle_binding_down(keybinding * binding)
161 { 191 {
162 switch(binding->bind_type) 192 if (binding->bind_type >= BIND_GAMEPAD1)
163 { 193 {
164 case BIND_GAMEPAD1: 194 if (binding->subtype_a <= GAMEPAD_EXTRA && binding->port) {
165 case BIND_GAMEPAD2: 195 binding->port->input[binding->subtype_a] |= binding->value;
166 if (binding->subtype_a <= GAMEPAD_EXTRA) { 196 }
167 genesis->ports[binding->bind_type - BIND_GAMEPAD1].input[binding->subtype_a] |= binding->value; 197 if (binding->subtype_b <= GAMEPAD_EXTRA && binding->port) {
168 } 198 binding->port->input[binding->subtype_b] |= binding->value;
169 if (binding->subtype_b <= GAMEPAD_EXTRA) { 199 }
170 genesis->ports[binding->bind_type - BIND_GAMEPAD1].input[binding->subtype_b] |= binding->value;
171 }
172 break;
173 } 200 }
174 } 201 }
175 202
176 void handle_keydown(int keycode) 203 void handle_keydown(int keycode)
177 { 204 {
204 { 231 {
205 switch(binding->bind_type) 232 switch(binding->bind_type)
206 { 233 {
207 case BIND_GAMEPAD1: 234 case BIND_GAMEPAD1:
208 case BIND_GAMEPAD2: 235 case BIND_GAMEPAD2:
209 if (binding->subtype_a <= GAMEPAD_EXTRA) { 236 if (binding->subtype_a <= GAMEPAD_EXTRA && binding->port) {
210 genesis->ports[binding->bind_type - BIND_GAMEPAD1].input[binding->subtype_a] &= ~binding->value; 237 binding->port->input[binding->subtype_a] &= ~binding->value;
211 } 238 }
212 if (binding->subtype_b <= GAMEPAD_EXTRA) { 239 if (binding->subtype_b <= GAMEPAD_EXTRA && binding->port) {
213 genesis->ports[binding->bind_type - BIND_GAMEPAD1].input[binding->subtype_b] &= ~binding->value; 240 binding->port->input[binding->subtype_b] &= ~binding->value;
214 } 241 }
215 break; 242 break;
216 case BIND_UI: 243 case BIND_UI:
217 switch (binding->subtype_a) 244 switch (binding->subtype_a)
218 { 245 {
445 if (curstr && len) { 472 if (curstr && len) {
446 free(curstr); 473 free(curstr);
447 } 474 }
448 } 475 }
449 476
450 void set_keybindings() 477 void process_device(char * device_type, io_port * port)
478 {
479 port->device_type = IO_NONE;
480 if (!device_type)
481 {
482 return;
483 }
484
485 const int gamepad_len = strlen("gamepad");
486 if (!memcmp(device_type, "gamepad", gamepad_len))
487 {
488 if (
489 (device_type[gamepad_len] != '3' && device_type[gamepad_len] != '6')
490 || device_type[gamepad_len+1] != '.' || device_type[gamepad_len+2] < '1'
491 || device_type[gamepad_len+2] > '8' || device_type[gamepad_len+3] != 0
492 )
493 {
494 fprintf(stderr, "%s is not a valid gamepad type\n", device_type);
495 } else if (device_type[gamepad_len] == '3')
496 {
497 port->device_type = IO_GAMEPAD3;
498 } else {
499 port->device_type = IO_GAMEPAD6;
500 }
501 port->device.pad.gamepad_num = device_type[gamepad_len+2] - '1';
502 } else if(!strcmp(device_type, "sega_parallel")) {
503 port->device_type = IO_SEGA_PARALLEL;
504 port->device.stream.data_fd = -1;
505 port->device.stream.listen_fd = -1;
506 } else if(!strcmp(device_type, "generic")) {
507 port->device_type = IO_GENERIC;
508 port->device.stream.data_fd = -1;
509 port->device.stream.listen_fd = -1;
510 }
511 }
512
513 char * io_name(int i)
514 {
515 switch (i)
516 {
517 case 0:
518 return "1";
519 case 1:
520 return "2";
521 case 2:
522 return "EXT";
523 default:
524 return "invalid";
525 }
526 }
527
528 static char * sockfile_name;
529 static void cleanup_sockfile()
530 {
531 unlink(sockfile_name);
532 }
533
534 void setup_io_devices(tern_node * config, io_port * ports)
535 {
536 tern_node *io_nodes = tern_find_prefix(config, "iodevices");
537 char * io_1 = tern_find_ptr(io_nodes, "1");
538 char * io_2 = tern_find_ptr(io_nodes, "2");
539 char * io_ext = tern_find_ptr(io_nodes, "ext");
540
541 process_device(io_1, ports);
542 process_device(io_2, ports+1);
543 process_device(io_ext, ports+2);
544
545 for (int i = 0; i < 3; i++)
546 {
547
548 if (ports[i].device_type == IO_SEGA_PARALLEL)
549 {
550 char *pipe_name = tern_find_ptr(config, "ioparallel_pipe");
551 if (!pipe_name)
552 {
553 fprintf(stderr, "IO port %s is configured to use the sega parallel board, but no paralell_pipe is set!\n", io_name(i));
554 ports[i].device_type = IO_NONE;
555 } else {
556 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);
557 if (!strcmp("stdin", pipe_name))
558 {
559 ports[i].device.stream.data_fd = STDIN_FILENO;
560 } else {
561 if (mkfifo(pipe_name, 0666) && errno != EEXIST)
562 {
563 fprintf(stderr, "Failed to create fifo %s for Sega parallel board emulation: %d %s\n", pipe_name, errno, strerror(errno));
564 ports[i].device_type = IO_NONE;
565 } else {
566 ports[i].device.stream.data_fd = open(pipe_name, O_NONBLOCK | O_RDONLY);
567 if (ports[i].device.stream.data_fd == -1)
568 {
569 fprintf(stderr, "Failed to open fifo %s for Sega parallel board emulation: %d %s\n", pipe_name, errno, strerror(errno));
570 ports[i].device_type = IO_NONE;
571 }
572 }
573 }
574 }
575 } else if (ports[i].device_type == IO_GENERIC) {
576 char *sock_name = tern_find_ptr(config, "iosocket");
577 if (!sock_name)
578 {
579 fprintf(stderr, "IO port %s is configured to use generic IO, but no socket is set!\n", io_name(i));
580 ports[i].device_type = IO_NONE;
581 } else {
582 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);
583 ports[i].device.stream.data_fd = -1;
584 ports[i].device.stream.listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
585 size_t pathlen = strlen(sock_name);
586 size_t addrlen = offsetof(struct sockaddr_un, sun_path) + pathlen + 1;
587 struct sockaddr_un *saddr = malloc(addrlen);
588 saddr->sun_family = AF_UNIX;
589 memcpy(saddr->sun_path, sock_name, pathlen+1);
590 if (bind(ports[i].device.stream.listen_fd, (struct sockaddr *)saddr, addrlen))
591 {
592 fprintf(stderr, "Failed to bind socket for IO Port %s to path %s: %d %s\n", io_name(i), sock_name, errno, strerror(errno));
593 goto cleanup_sock;
594 }
595 if (listen(ports[i].device.stream.listen_fd, 1))
596 {
597 fprintf(stderr, "Failed to listen on socket for IO Port %s: %d %s\n", io_name(i), errno, strerror(errno));
598 goto cleanup_sockfile;
599 }
600 sockfile_name = sock_name;
601 atexit(cleanup_sockfile);
602 continue;
603 cleanup_sockfile:
604 unlink(sock_name);
605 cleanup_sock:
606 close(ports[i].device.stream.listen_fd);
607 ports[i].device_type = IO_NONE;
608 }
609 } else if (ports[i].device_type == IO_GAMEPAD3 || ports[i].device_type == IO_GAMEPAD6) {
610 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]);
611 } else {
612 printf("IO port %s connected to device '%s'\n", io_name(i), device_type_names[ports[i].device_type]);
613 }
614 }
615 }
616
617 void map_bindings(io_port *ports, keybinding *bindings, int numbindings)
618 {
619 for (int i = 0; i < numbindings; i++)
620 {
621 if (bindings[i].bind_type >= BIND_GAMEPAD1)
622 {
623 int num = bindings[i].bind_type - BIND_GAMEPAD1;
624 for (int j = 0; j < 3; j++)
625 {
626 if ((ports[j].device_type == IO_GAMEPAD3
627 || ports[j].device_type ==IO_GAMEPAD6)
628 && ports[j].device.pad.gamepad_num == num
629 )
630 {
631 bindings[i].port = ports + j;
632 break;
633 }
634 }
635 }
636 }
637 }
638
639 void set_keybindings(io_port *ports)
451 { 640 {
452 tern_node * special = tern_insert_int(NULL, "up", RENDERKEY_UP); 641 tern_node * special = tern_insert_int(NULL, "up", RENDERKEY_UP);
453 special = tern_insert_int(special, "down", RENDERKEY_DOWN); 642 special = tern_insert_int(special, "down", RENDERKEY_DOWN);
454 special = tern_insert_int(special, "left", RENDERKEY_LEFT); 643 special = tern_insert_int(special, "left", RENDERKEY_LEFT);
455 special = tern_insert_int(special, "right", RENDERKEY_RIGHT); 644 special = tern_insert_int(special, "right", RENDERKEY_RIGHT);
530 } 719 }
531 tern_node * speed_nodes = tern_find_prefix(config, "clocksspeeds"); 720 tern_node * speed_nodes = tern_find_prefix(config, "clocksspeeds");
532 speeds = malloc(sizeof(uint32_t)); 721 speeds = malloc(sizeof(uint32_t));
533 speeds[0] = 100; 722 speeds[0] = 100;
534 process_speeds(speed_nodes, NULL); 723 process_speeds(speed_nodes, NULL);
535 for (int i = 0; i < num_speeds; i++) { 724 for (int i = 0; i < num_speeds; i++)
725 {
536 if (!speeds[i]) { 726 if (!speeds[i]) {
537 fprintf(stderr, "Speed index %d was not set to a valid percentage!", i); 727 fprintf(stderr, "Speed index %d was not set to a valid percentage!", i);
538 speeds[i] = 100; 728 speeds[i] = 100;
539 } 729 }
540 } 730 }
731 for (int bucket = 0; bucket < 256; bucket++)
732 {
733 if (bindings[bucket])
734 {
735 map_bindings(ports, bindings[bucket], 256);
736 }
737 }
738 for (int stick = 0; stick < MAX_JOYSTICKS; stick++)
739 {
740 if (joybindings[stick])
741 {
742 int numbuttons = render_joystick_num_buttons(stick);
743 map_bindings(ports, joybindings[stick], render_joystick_num_buttons(stick));
744 }
745 if (joydpads[stick])
746 {
747 map_bindings(ports, joydpads[stick]->bindings, 4);
748 }
749 }
541 } 750 }
542 751
543 #define TH 0x40 752 #define TH 0x40
544 #define TH_TIMEOUT 8000 753 #define TH_TIMEOUT 8000
545 754
546 void io_adjust_cycles(io_port * pad, uint32_t current_cycle, uint32_t deduction) 755 void io_adjust_cycles(io_port * port, uint32_t current_cycle, uint32_t deduction)
547 { 756 {
548 /*uint8_t control = pad->control | 0x80; 757 /*uint8_t control = pad->control | 0x80;
549 uint8_t th = control & pad->output; 758 uint8_t th = control & pad->output;
550 if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) { 759 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); 760 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 }*/ 761 }*/
553 if (current_cycle >= pad->timeout_cycle) { 762 if (port->device_type == IO_GAMEPAD6)
554 pad->th_counter = 0; 763 {
555 } else { 764 if (current_cycle >= port->device.pad.timeout_cycle)
556 pad->timeout_cycle -= deduction; 765 {
557 } 766 port->device.pad.th_counter = 0;
558 } 767 } else {
559 768 port->device.pad.timeout_cycle -= deduction;
560 void io_data_write(io_port * pad, uint8_t value, uint32_t current_cycle) 769 }
561 { 770 }
562 if (pad->control & TH) { 771 }
563 //check if TH has changed 772
564 if ((pad->output & TH) ^ (value & TH)) { 773 static void wait_for_connection(io_port * port)
565 if (current_cycle >= pad->timeout_cycle) { 774 {
566 pad->th_counter = 0; 775 if (port->device.stream.data_fd == -1)
567 } 776 {
568 if (!(value & TH)) { 777 puts("Waiting for socket connection...");
569 pad->th_counter++; 778 port->device.stream.data_fd = accept(port->device.stream.listen_fd, NULL, NULL);
570 } 779 fcntl(port->device.stream.data_fd, F_SETFL, O_NONBLOCK | O_RDWR);
571 pad->timeout_cycle = current_cycle + TH_TIMEOUT; 780 }
572 } 781 }
573 } 782
574 pad->output = value; 783 static void service_pipe(io_port * port)
575 } 784 {
576 785 uint8_t value;
577 uint8_t io_data_read(io_port * pad, uint32_t current_cycle) 786 int numRead = read(port->device.stream.data_fd, &value, sizeof(value));
578 { 787 if (numRead > 0)
579 uint8_t control = pad->control | 0x80; 788 {
580 uint8_t th = control & pad->output; 789 port->input[IO_TH0] = (value & 0xF) | 0x10;
790 port->input[IO_TH1] = (value >> 4) | 0x10;
791 } else if(numRead == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
792 fprintf(stderr, "Error reading pipe for IO port: %d %s\n", errno, strerror(errno));
793 }
794 }
795
796 static void service_socket(io_port *port)
797 {
798 uint8_t buf[32];
799 uint8_t blocking = 0;
800 int numRead = 0;
801 while (numRead <= 0)
802 {
803 numRead = recv(port->device.stream.data_fd, buf, sizeof(buf), 0);
804 if (numRead > 0)
805 {
806 port->input[IO_TH0] = buf[numRead-1];
807 if (port->input[IO_STATE] == IO_READ_PENDING)
808 {
809 port->input[IO_STATE] = IO_READ;
810 if (blocking)
811 {
812 //pending read satisfied, back to non-blocking mode
813 fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR | O_NONBLOCK);
814 }
815 } else if (port->input[IO_STATE] == IO_WRITTEN) {
816 port->input[IO_STATE] = IO_READ;
817 }
818 } else if (numRead == 0) {
819 port->device.stream.data_fd = -1;
820 wait_for_connection(port);
821 } else if (errno != EAGAIN && errno != EWOULDBLOCK) {
822 fprintf(stderr, "Error reading from socket for IO port: %d %s\n", errno, strerror(errno));
823 close(port->device.stream.data_fd);
824 wait_for_connection(port);
825 } else if (port->input[IO_STATE] == IO_READ_PENDING) {
826 //clear the nonblocking flag so the next read will block
827 if (!blocking)
828 {
829 fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR);
830 blocking = 1;
831 }
832 } else {
833 //no new data, but that's ok
834 break;
835 }
836 }
837
838 if (port->input[IO_STATE] == IO_WRITE_PENDING)
839 {
840 uint8_t value = port->output & port->control;
841 int written = 0;
842 blocking = 0;
843 while (written <= 0)
844 {
845 send(port->device.stream.data_fd, &value, sizeof(value), 0);
846 if (written > 0)
847 {
848 port->input[IO_STATE] = IO_WRITTEN;
849 if (blocking)
850 {
851 //pending write satisfied, back to non-blocking mode
852 fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR | O_NONBLOCK);
853 }
854 } else if (written == 0) {
855 port->device.stream.data_fd = -1;
856 wait_for_connection(port);
857 } else if (errno != EAGAIN && errno != EWOULDBLOCK) {
858 fprintf(stderr, "Error writing to socket for IO port: %d %s\n", errno, strerror(errno));
859 close(port->device.stream.data_fd);
860 wait_for_connection(port);
861 } else {
862 //clear the nonblocking flag so the next write will block
863 if (!blocking)
864 {
865 fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR);
866 blocking = 1;
867 }
868 }
869 }
870 }
871 }
872
873 void io_data_write(io_port * port, uint8_t value, uint32_t current_cycle)
874 {
875 switch (port->device_type)
876 {
877 case IO_GAMEPAD6:
878 if (port->control & TH) {
879 //check if TH has changed
880 if ((port->output & TH) ^ (value & TH)) {
881 if (current_cycle >= port->device.pad.timeout_cycle) {
882 port->device.pad.th_counter = 0;
883 }
884 if (!(value & TH)) {
885 port->device.pad.th_counter++;
886 }
887 port->device.pad.timeout_cycle = current_cycle + TH_TIMEOUT;
888 }
889 }
890 port->output = value;
891 break;
892 case IO_GENERIC:
893 wait_for_connection(port);
894 port->input[IO_STATE] = IO_WRITE_PENDING;
895 port->output = value;
896 service_socket(port);
897 break;
898 default:
899 port->output = value;
900 }
901
902 }
903
904 uint8_t io_data_read(io_port * port, uint32_t current_cycle)
905 {
906 uint8_t control = port->control | 0x80;
907 uint8_t th = control & port->output & 0x40;
581 uint8_t input; 908 uint8_t input;
582 if (current_cycle >= pad->timeout_cycle) { 909 switch (port->device_type)
583 pad->th_counter = 0; 910 {
584 } 911 case IO_GAMEPAD3:
585 /*if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) { 912 {
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); 913 input = port->input[th ? GAMEPAD_TH1 : GAMEPAD_TH0];
587 }*/ 914 break;
588 if (th) { 915 }
589 if (pad->th_counter == 3) { 916 case IO_GAMEPAD6:
590 input = pad->input[GAMEPAD_EXTRA]; 917 {
918 if (current_cycle >= port->device.pad.timeout_cycle) {
919 port->device.pad.th_counter = 0;
920 }
921 /*if (port->input[GAMEPAD_TH0] || port->input[GAMEPAD_TH1]) {
922 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);
923 }*/
924 if (th) {
925 if (port->device.pad.th_counter == 3) {
926 input = port->input[GAMEPAD_EXTRA];
927 } else {
928 input = port->input[GAMEPAD_TH1];
929 }
591 } else { 930 } else {
592 input = pad->input[GAMEPAD_TH1]; 931 if (port->device.pad.th_counter == 3) {
593 } 932 input = port->input[GAMEPAD_TH0] | 0xF;
594 } else { 933 } else if(port->device.pad.th_counter == 4) {
595 if (pad->th_counter == 3) { 934 input = port->input[GAMEPAD_TH0] & 0x30;
596 input = pad->input[GAMEPAD_TH0] | 0xF; 935 } else {
597 } else if(pad->th_counter == 4) { 936 input = port->input[GAMEPAD_TH0] | 0xC;
598 input = pad->input[GAMEPAD_TH0] & 0x30; 937 }
599 } else { 938 }
600 input = pad->input[GAMEPAD_TH0] | 0xC; 939 break;
601 } 940 }
602 } 941 case IO_SEGA_PARALLEL:
603 uint8_t value = ((~input) & (~control)) | (pad->output & control); 942 if (!th)
604 /*if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) { 943 {
944 service_pipe(port);
945 }
946 input = ~port->input[th ? IO_TH1 : IO_TH0];
947 break;
948 case IO_GENERIC:
949 if (port->input[IO_TH0] & 0x80 && port->input[IO_STATE] == IO_WRITTEN)
950 {
951 //device requested a blocking read after writes
952 port->input[IO_STATE] = IO_READ_PENDING;
953 }
954 service_socket(port);
955 input = ~port->input[IO_TH0];
956 break;
957 default:
958 input = 0;
959 break;
960 }
961 uint8_t value = ((~input) & (~control)) | (port->output & control);
962 /*if (port->input[GAMEPAD_TH0] || port->input[GAMEPAD_TH1]) {
605 printf ("value: %X\n", value); 963 printf ("value: %X\n", value);
606 }*/ 964 }*/
607 return value; 965 return value;
608 } 966 }
609 967