main io.c
   1/*
   2 Copyright 2013 Michael Pavone
   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.
   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#include <stdlib.h>
  15
  16#include "serialize.h"
  17#include "io.h"
  18#include "blastem.h"
  19#include "render.h"
  20#include "util.h"
  21#include "bindings.h"
  22
  23#define CYCLE_NEVER 0xFFFFFFFF
  24#define MIN_POLL_INTERVAL 6840
  25
  26const char * device_type_names[] = {
  27	"None",
  28	"SMS gamepad",
  29	"3-button gamepad",
  30	"6-button gamepad",
  31	"Mega Mouse",
  32	"Saturn Keyboard",
  33	"XBAND Keyboard",
  34	"Menacer",
  35	"Justifier",
  36	"Sega multi-tap",
  37	"EA 4-way Play cable A",
  38	"EA 4-way Play cable B",
  39	"Sega Parallel Transfer Board",
  40	"Generic Device"
  41};
  42
  43#define GAMEPAD_TH0 0
  44#define GAMEPAD_TH1 1
  45#define GAMEPAD_EXTRA 2
  46#define GAMEPAD_NONE 0xF
  47
  48#define IO_TH0 0
  49#define IO_TH1 1
  50#define IO_STATE 2
  51
  52enum {
  53	IO_WRITE_PENDING,
  54	IO_WRITTEN,
  55	IO_READ_PENDING,
  56	IO_READ
  57};
  58
  59typedef struct {
  60	uint8_t states[2], value;
  61} gp_button_def;
  62
  63
  64static gp_button_def button_defs[NUM_GAMEPAD_BUTTONS] = {
  65	[DPAD_UP] = {.states = {GAMEPAD_TH0, GAMEPAD_TH1}, .value = 0x1},
  66	[DPAD_DOWN] = {.states = {GAMEPAD_TH0, GAMEPAD_TH1}, .value = 0x2},
  67	[DPAD_LEFT] = {.states = {GAMEPAD_TH1, GAMEPAD_NONE}, .value = 0x4},
  68	[DPAD_RIGHT] = {.states = {GAMEPAD_TH1, GAMEPAD_NONE}, .value = 0x8},
  69	[BUTTON_A] = {.states = {GAMEPAD_TH0, GAMEPAD_NONE}, .value = 0x10},
  70	[BUTTON_B] = {.states = {GAMEPAD_TH1, GAMEPAD_NONE}, .value = 0x10},
  71	[BUTTON_C] = {.states = {GAMEPAD_TH1, GAMEPAD_NONE}, .value = 0x20},
  72	[BUTTON_START] = {.states = {GAMEPAD_TH0, GAMEPAD_NONE}, .value = 0x20},
  73	[BUTTON_X] = {.states = {GAMEPAD_EXTRA, GAMEPAD_NONE}, .value = 0x4},
  74	[BUTTON_Y] = {.states = {GAMEPAD_EXTRA, GAMEPAD_NONE}, .value = 0x2},
  75	[BUTTON_Z] = {.states = {GAMEPAD_EXTRA, GAMEPAD_NONE}, .value = 0x1},
  76	[BUTTON_MODE] = {.states = {GAMEPAD_EXTRA, GAMEPAD_NONE}, .value = 0x8},
  77};
  78
  79static io_port *find_gamepad(sega_io *io, uint8_t gamepad_num)
  80{
  81	for (int i = 0; i < 3; i++)
  82	{
  83		io_port *port = io->ports + i;
  84		if (port->device_type < IO_MOUSE && port->device.pad.gamepad_num == gamepad_num) {
  85			return port;
  86		}
  87	}
  88	return NULL;
  89}
  90
  91static io_port *find_mouse(sega_io *io, uint8_t mouse_num)
  92{
  93	for (int i = 0; i < 3; i++)
  94	{
  95		io_port *port = io->ports + i;
  96		if (port->device_type == IO_MOUSE && port->device.mouse.mouse_num == mouse_num) {
  97			return port;
  98		}
  99	}
 100	return NULL;
 101}
 102
 103static io_port *find_keyboard(sega_io *io)
 104{
 105	for (int i = 0; i < 3; i++)
 106	{
 107		io_port *port = io->ports + i;
 108		if (port->device_type == IO_SATURN_KEYBOARD || port->device_type == IO_XBAND_KEYBOARD) {
 109			return port;
 110		}
 111	}
 112	return NULL;
 113}
 114
 115void io_port_gamepad_down(io_port *port, uint8_t button)
 116{
 117	gp_button_def *def = button_defs + button;
 118	port->input[def->states[0]] |= def->value;
 119	if (def->states[1] != GAMEPAD_NONE) {
 120		port->input[def->states[1]] |= def->value;
 121	}
 122}
 123
 124void io_port_gamepad_up(io_port *port, uint8_t button)
 125{
 126	gp_button_def *def = button_defs + button;
 127	port->input[def->states[0]] &= ~def->value;
 128	if (def->states[1] != GAMEPAD_NONE) {
 129		port->input[def->states[1]] &= ~def->value;
 130	}
 131}
 132
 133void io_gamepad_down(sega_io *io, uint8_t gamepad_num, uint8_t button)
 134{
 135	io_port *port = find_gamepad(io, gamepad_num);
 136	if (port) {
 137		io_port_gamepad_down(port, button);
 138	}
 139}
 140
 141void io_gamepad_up(sega_io *io, uint8_t gamepad_num, uint8_t button)
 142{
 143	io_port *port = find_gamepad(io, gamepad_num);
 144	if (port) {
 145		io_port_gamepad_up(port, button);
 146	}
 147}
 148
 149void io_mouse_down(sega_io *io, uint8_t mouse_num, uint8_t button)
 150{
 151	io_port *port = find_mouse(io, mouse_num);
 152	if (port) {
 153		port->input[0] |= button;
 154	}
 155}
 156
 157void io_mouse_up(sega_io *io, uint8_t mouse_num, uint8_t button)
 158{
 159	io_port *port = find_mouse(io, mouse_num);
 160	if (port) {
 161		port->input[0] &= ~button;
 162	}
 163}
 164
 165void io_mouse_motion_absolute(sega_io *io, uint8_t mouse_num, uint16_t x, uint16_t y)
 166{
 167	io_port *port = find_mouse(io, mouse_num);
 168	if (port) {
 169		port->device.mouse.cur_x = x;
 170		port->device.mouse.cur_y = y;
 171	}
 172}
 173
 174void io_mouse_motion_relative(sega_io *io, uint8_t mouse_num, int32_t x, int32_t y)
 175{
 176	io_port *port = find_mouse(io, mouse_num);
 177	if (port) {
 178		port->device.mouse.cur_x += x;
 179		port->device.mouse.cur_y += y;
 180	}
 181}
 182
 183void store_key_event(io_port *keyboard_port, uint16_t code)
 184{
 185	if (keyboard_port && keyboard_port->device.keyboard.write_pos != keyboard_port->device.keyboard.read_pos) {
 186		//there's room in the buffer, record this event
 187		keyboard_port->device.keyboard.events[keyboard_port->device.keyboard.write_pos] = code;
 188		if (keyboard_port->device.keyboard.read_pos == 0xFF) {
 189			//ring buffer was empty, update read_pos to indicate there is now data
 190			keyboard_port->device.keyboard.read_pos = keyboard_port->device.keyboard.write_pos;
 191		}
 192		keyboard_port->device.keyboard.write_pos = (keyboard_port->device.keyboard.write_pos + 1) & 7;
 193	}
 194}
 195
 196void io_keyboard_down(sega_io *io, uint8_t scancode)
 197{
 198	store_key_event(find_keyboard(io), scancode);
 199}
 200
 201void io_keyboard_up(sega_io *io, uint8_t scancode)
 202{
 203	store_key_event(find_keyboard(io), 0xF000 | scancode);
 204}
 205
 206uint8_t io_has_keyboard(sega_io *io)
 207{
 208	return find_keyboard(io) != NULL;
 209}
 210
 211void process_device(char * device_type, io_port * port)
 212{
 213	//assuming that the io_port struct has been zeroed if this is the first time this has been called
 214	if (!device_type)
 215	{
 216		return;
 217	}
 218
 219	const int gamepad_len = strlen("gamepad");
 220	if (startswith(device_type, "gamepad"))
 221	{
 222		if (
 223			(device_type[gamepad_len] != '3' && device_type[gamepad_len] != '6' && device_type[gamepad_len] != '2')
 224			|| device_type[gamepad_len+1] != '.' || device_type[gamepad_len+2] < '1'
 225			|| device_type[gamepad_len+2] > '8' || device_type[gamepad_len+3] != 0
 226		) {
 227			warning("%s is not a valid gamepad type\n", device_type);
 228		} else if (device_type[gamepad_len] == '3') {
 229			port->device_type = IO_GAMEPAD3;
 230		} else if (device_type[gamepad_len] == '2') {
 231			port->device_type = IO_GAMEPAD2;
 232		} else {
 233			port->device_type = IO_GAMEPAD6;
 234		}
 235		port->device.pad.gamepad_num = device_type[gamepad_len+2] - '0';
 236	} else if(startswith(device_type, "mouse")) {
 237		if (port->device_type != IO_MOUSE) {
 238			port->device_type = IO_MOUSE;
 239			port->device.mouse.mouse_num = device_type[strlen("mouse")+1] - '0';
 240			port->device.mouse.last_read_x = 0;
 241			port->device.mouse.last_read_y = 0;
 242			port->device.mouse.cur_x = 0;
 243			port->device.mouse.cur_y = 0;
 244			port->device.mouse.latched_x = 0;
 245			port->device.mouse.latched_y = 0;
 246			port->device.mouse.ready_cycle = CYCLE_NEVER;
 247			port->device.mouse.tr_counter = 0;
 248		}
 249	} else if(!strcmp(device_type, "saturn keyboard")) {
 250		if (port->device_type != IO_SATURN_KEYBOARD) {
 251			port->device_type = IO_SATURN_KEYBOARD;
 252			port->device.keyboard.read_pos = 0xFF;
 253			port->device.keyboard.write_pos = 0;
 254		}
 255	} else if(!strcmp(device_type, "xband keyboard")) {
 256		if (port->device_type != IO_XBAND_KEYBOARD) {
 257			port->device_type = IO_XBAND_KEYBOARD;
 258			port->device.keyboard.read_pos = 0xFF;
 259			port->device.keyboard.write_pos = 0;
 260		}
 261	} else if(!strcmp(device_type, "sega_parallel")) {
 262		if (port->device_type != IO_SEGA_PARALLEL) {
 263			port->device_type = IO_SEGA_PARALLEL;
 264			port->device.stream.data_fd = -1;
 265			port->device.stream.listen_fd = -1;
 266		}
 267	} else if(!strcmp(device_type, "generic")) {
 268		if (port->device_type != IO_GENERIC) {
 269			port->device_type = IO_GENERIC;
 270			port->device.stream.data_fd = -1;
 271			port->device.stream.listen_fd = -1;
 272		}
 273	}
 274}
 275
 276char * io_name(int i)
 277{
 278	switch (i)
 279	{
 280	case 0:
 281		return "1";
 282	case 1:
 283		return "2";
 284	case 2:
 285		return "EXT";
 286	default:
 287		return "invalid";
 288	}
 289}
 290
 291static char * sockfile_name;
 292static void cleanup_sockfile()
 293{
 294	unlink(sockfile_name);
 295}
 296
 297void setup_io_devices(tern_node * config, rom_info *rom, sega_io *io)
 298{
 299	io_port * ports = io->ports;
 300	tern_node *io_nodes = tern_find_path(config, "io\0devices\0", TVAL_NODE).ptrval;
 301	char * io_1 = rom->port1_override ? rom->port1_override : tern_find_ptr_default(io_nodes, "1", "gamepad6.1");
 302	char * io_2 = rom->port2_override ? rom->port2_override : tern_find_ptr_default(io_nodes, "2", "gamepad6.2");
 303	char * io_ext = rom->ext_override ? rom->ext_override : tern_find_ptr(io_nodes, "ext");
 304
 305	process_device(io_1, ports);
 306	process_device(io_2, ports+1);
 307	process_device(io_ext, ports+2);
 308
 309	uint8_t mouse_mode;
 310	if (ports[0].device_type == IO_MOUSE || ports[1].device_type == IO_MOUSE || ports[2].device_type == IO_MOUSE) {
 311		if (rom->mouse_mode && !strcmp(rom->mouse_mode, "absolute")) {
 312			mouse_mode = MOUSE_ABSOLUTE;
 313		} else {
 314			mouse_mode = MOUSE_CAPTURE;
 315		}
 316	} else {
 317		mouse_mode = MOUSE_NONE;
 318	}
 319	bindings_set_mouse_mode(mouse_mode);
 320
 321	for (int i = 0; i < 3; i++)
 322	{
 323		if (ports[i].device_type == IO_SEGA_PARALLEL && ports[i].device.stream.data_fd == -1)
 324		{
 325			char *pipe_name = tern_find_path(config, "io\0parallel_pipe\0", TVAL_PTR).ptrval;
 326			if (!pipe_name)
 327			{
 328				warning("IO port %s is configured to use the sega parallel board, but no paralell_pipe is set!\n", io_name(i));
 329				ports[i].device_type = IO_NONE;
 330			} else {
 331				debug_message("IO port: %s connected to device '%s' with pipe name: %s\n", io_name(i), device_type_names[ports[i].device_type], pipe_name);
 332				if (!strcmp("stdin", pipe_name))
 333				{
 334					ports[i].device.stream.data_fd = STDIN_FILENO;
 335				} else {
 336					if (mkfifo(pipe_name, 0666) && errno != EEXIST)
 337					{
 338						warning("Failed to create fifo %s for Sega parallel board emulation: %d %s\n", pipe_name, errno, strerror(errno));
 339						ports[i].device_type = IO_NONE;
 340					} else {
 341						ports[i].device.stream.data_fd = open(pipe_name, O_NONBLOCK | O_RDONLY);
 342						if (ports[i].device.stream.data_fd == -1)
 343						{
 344							warning("Failed to open fifo %s for Sega parallel board emulation: %d %s\n", pipe_name, errno, strerror(errno));
 345							ports[i].device_type = IO_NONE;
 346						}
 347					}
 348				}
 349			}
 350		} else if (ports[i].device_type == IO_GENERIC && ports[i].device.stream.data_fd == -1) {
 351			char *sock_name = tern_find_path(config, "io\0socket\0", TVAL_PTR).ptrval;
 352			if (!sock_name)
 353			{
 354				warning("IO port %s is configured to use generic IO, but no socket is set!\n", io_name(i));
 355				ports[i].device_type = IO_NONE;
 356			} else {
 357				debug_message("IO port: %s connected to device '%s' with socket name: %s\n", io_name(i), device_type_names[ports[i].device_type], sock_name);
 358				ports[i].device.stream.data_fd = -1;
 359				ports[i].device.stream.listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
 360				size_t pathlen = strlen(sock_name);
 361				size_t addrlen = offsetof(struct sockaddr_un, sun_path) + pathlen + 1;
 362				struct sockaddr_un *saddr = malloc(addrlen);
 363				saddr->sun_family = AF_UNIX;
 364				memcpy(saddr->sun_path, sock_name, pathlen+1);
 365				if (bind(ports[i].device.stream.listen_fd, (struct sockaddr *)saddr, addrlen))
 366				{
 367					warning("Failed to bind socket for IO Port %s to path %s: %d %s\n", io_name(i), sock_name, errno, strerror(errno));
 368					goto cleanup_sock;
 369				}
 370				if (listen(ports[i].device.stream.listen_fd, 1))
 371				{
 372					warning("Failed to listen on socket for IO Port %s: %d %s\n", io_name(i), errno, strerror(errno));
 373					goto cleanup_sockfile;
 374				}
 375				sockfile_name = sock_name;
 376				atexit(cleanup_sockfile);
 377				continue;
 378cleanup_sockfile:
 379				unlink(sock_name);
 380cleanup_sock:
 381				close(ports[i].device.stream.listen_fd);
 382				ports[i].device_type = IO_NONE;
 383			}
 384		} else
 385		if (ports[i].device_type == IO_GAMEPAD3 || ports[i].device_type == IO_GAMEPAD6 || ports[i].device_type == IO_GAMEPAD2) {
 386			debug_message("IO port %s connected to gamepad #%d with type '%s'\n", io_name(i), ports[i].device.pad.gamepad_num, device_type_names[ports[i].device_type]);
 387		} else {
 388			debug_message("IO port %s connected to device '%s'\n", io_name(i), device_type_names[ports[i].device_type]);
 389		}
 390	}
 391}
 392
 393
 394#define TH 0x40
 395#define TR 0x20
 396#define TH_TIMEOUT 56000
 397
 398void mouse_check_ready(io_port *port, uint32_t current_cycle)
 399{
 400	if (current_cycle >= port->device.mouse.ready_cycle) {
 401		port->device.mouse.tr_counter++;
 402		port->device.mouse.ready_cycle = CYCLE_NEVER;
 403		if (port->device.mouse.tr_counter == 3) {
 404			port->device.mouse.latched_x = port->device.mouse.cur_x;
 405			port->device.mouse.latched_y = port->device.mouse.cur_y;
 406			/* FIXME mouse mode owned by bindings now
 407			if (current_io->mouse_mode == MOUSE_ABSOLUTE) {
 408				//avoid overflow in absolute mode
 409				int deltax = port->device.mouse.latched_x - port->device.mouse.last_read_x;
 410				if (abs(deltax) > 255) {
 411					port->device.mouse.latched_x = port->device.mouse.last_read_x + (deltax > 0 ? 255 : -255);
 412				}
 413				int deltay = port->device.mouse.latched_y - port->device.mouse.last_read_y;
 414				if (abs(deltay) > 255) {
 415					port->device.mouse.latched_y = port->device.mouse.last_read_y + (deltay > 0 ? 255 : -255);
 416				}
 417			}*/
 418		}
 419	}
 420}
 421
 422uint32_t last_poll_cycle;
 423void io_adjust_cycles(io_port * port, uint32_t current_cycle, uint32_t deduction)
 424{
 425	/*uint8_t control = pad->control | 0x80;
 426	uint8_t th = control & pad->output;
 427	if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) {
 428		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);
 429	}*/
 430	if (port->device_type == IO_GAMEPAD6)
 431	{
 432		if (current_cycle >= port->device.pad.timeout_cycle)
 433		{
 434			port->device.pad.th_counter = 0;
 435		} else {
 436			port->device.pad.timeout_cycle -= deduction;
 437		}
 438	} else if (port->device_type == IO_MOUSE) {
 439		mouse_check_ready(port, current_cycle);
 440		if (port->device.mouse.ready_cycle != CYCLE_NEVER) {
 441			port->device.mouse.ready_cycle -= deduction;
 442		}
 443	}
 444	for (int i = 0; i < 8; i++)
 445	{
 446		if (port->slow_rise_start[i] != CYCLE_NEVER) {
 447			if (port->slow_rise_start[i] >= deduction) {
 448				port->slow_rise_start[i] -= deduction;
 449			} else {
 450				port->slow_rise_start[i] = CYCLE_NEVER;
 451			}
 452		}
 453	}
 454	if (last_poll_cycle >= deduction) {
 455		last_poll_cycle -= deduction;
 456	} else {
 457		last_poll_cycle = 0;
 458	}
 459}
 460
 461static void wait_for_connection(io_port * port)
 462{
 463	if (port->device.stream.data_fd == -1)
 464	{
 465		debug_message("Waiting for socket connection...");
 466		port->device.stream.data_fd = accept(port->device.stream.listen_fd, NULL, NULL);
 467		fcntl(port->device.stream.data_fd, F_SETFL, O_NONBLOCK | O_RDWR);
 468	}
 469}
 470
 471static void service_pipe(io_port * port)
 472{
 473	uint8_t value;
 474	int numRead = read(port->device.stream.data_fd, &value, sizeof(value));
 475	if (numRead > 0)
 476	{
 477		port->input[IO_TH0] = (value & 0xF) | 0x10;
 478		port->input[IO_TH1] = (value >> 4) | 0x10;
 479	} else if(numRead == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
 480		warning("Error reading pipe for IO port: %d %s\n", errno, strerror(errno));
 481	}
 482}
 483
 484static void service_socket(io_port *port)
 485{
 486	uint8_t buf[32];
 487	uint8_t blocking = 0;
 488	int numRead = 0;
 489	while (numRead <= 0)
 490	{
 491		numRead = recv(port->device.stream.data_fd, buf, sizeof(buf), 0);
 492		if (numRead > 0)
 493		{
 494			port->input[IO_TH0] = buf[numRead-1];
 495			if (port->input[IO_STATE] == IO_READ_PENDING)
 496			{
 497				port->input[IO_STATE] = IO_READ;
 498				if (blocking)
 499				{
 500					//pending read satisfied, back to non-blocking mode
 501					fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR | O_NONBLOCK);
 502				}
 503			} else if (port->input[IO_STATE] == IO_WRITTEN) {
 504				port->input[IO_STATE] = IO_READ;
 505			}
 506		} else if (numRead == 0) {
 507			port->device.stream.data_fd = -1;
 508			wait_for_connection(port);
 509		} else if (errno != EAGAIN && errno != EWOULDBLOCK) {
 510			warning("Error reading from socket for IO port: %d %s\n", errno, strerror(errno));
 511			close(port->device.stream.data_fd);
 512			wait_for_connection(port);
 513		} else if (port->input[IO_STATE] == IO_READ_PENDING) {
 514			//clear the nonblocking flag so the next read will block
 515			if (!blocking)
 516			{
 517				fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR);
 518				blocking = 1;
 519			}
 520		} else {
 521			//no new data, but that's ok
 522			break;
 523		}
 524	}
 525
 526	if (port->input[IO_STATE] == IO_WRITE_PENDING)
 527	{
 528		uint8_t value = port->output & port->control;
 529		int written = 0;
 530		blocking = 0;
 531		while (written <= 0)
 532		{
 533			send(port->device.stream.data_fd, &value, sizeof(value), 0);
 534			if (written > 0)
 535			{
 536				port->input[IO_STATE] = IO_WRITTEN;
 537				if (blocking)
 538				{
 539					//pending write satisfied, back to non-blocking mode
 540					fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR | O_NONBLOCK);
 541				}
 542			} else if (written == 0) {
 543				port->device.stream.data_fd = -1;
 544				wait_for_connection(port);
 545			} else if (errno != EAGAIN && errno != EWOULDBLOCK) {
 546				warning("Error writing to socket for IO port: %d %s\n", errno, strerror(errno));
 547				close(port->device.stream.data_fd);
 548				wait_for_connection(port);
 549			} else {
 550				//clear the nonblocking flag so the next write will block
 551				if (!blocking)
 552				{
 553					fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR);
 554					blocking = 1;
 555				}
 556			}
 557		}
 558	}
 559}
 560
 561const int mouse_delays[] = {112*7, 120*7, 96*7, 132*7, 104*7, 96*7, 112*7, 96*7};
 562
 563enum {
 564	KB_SETUP,
 565	KB_READ,
 566	KB_WRITE
 567};
 568
 569void io_control_write(io_port *port, uint8_t value, uint32_t current_cycle)
 570{
 571	uint8_t changes = value ^ port->control;
 572	if (changes) {
 573		for (int i = 0; i < 8; i++)
 574		{
 575			if (!(value & 1 << i) && !(port->output & 1 << i)) {
 576				//port switched from output to input and the output value was 0
 577				//since there is a weak pull-up on input pins, this will lead
 578				//to a slow rise from 0 to 1 if the pin isn't being externally driven
 579				port->slow_rise_start[i] = current_cycle;
 580			} else {
 581				port->slow_rise_start[i] = CYCLE_NEVER;
 582			}
 583		}
 584		port->control = value;
 585	}
 586}
 587
 588void io_data_write(io_port * port, uint8_t value, uint32_t current_cycle)
 589{
 590	uint8_t old_output = (port->control & port->output) | (~port->control & 0xFF);
 591	uint8_t output = (port->control & value) | (~port->control & 0xFF);
 592	switch (port->device_type)
 593	{
 594	case IO_GAMEPAD6:
 595		//check if TH has changed
 596		if ((old_output & TH) ^ (output & TH)) {
 597			if (current_cycle >= port->device.pad.timeout_cycle) {
 598				port->device.pad.th_counter = 0;
 599			}
 600			if ((output & TH)) {
 601				port->device.pad.th_counter++;
 602			}
 603			port->device.pad.timeout_cycle = current_cycle + TH_TIMEOUT;
 604		}
 605		break;
 606	case IO_MOUSE:
 607		mouse_check_ready(port, current_cycle);
 608		if (output & TH) {
 609			//request is over or mouse is being reset
 610			if (port->device.mouse.tr_counter) {
 611				//request is over
 612				port->device.mouse.last_read_x = port->device.mouse.latched_x;
 613				port->device.mouse.last_read_y = port->device.mouse.latched_y;
 614			}
 615			port->device.mouse.tr_counter = 0;
 616			port->device.mouse.ready_cycle = CYCLE_NEVER;
 617		} else {
 618			if ((output & TR) != (old_output & TR)) {
 619				int delay_index = port->device.mouse.tr_counter >= sizeof(mouse_delays) ? sizeof(mouse_delays)-1 : port->device.mouse.tr_counter;
 620				port->device.mouse.ready_cycle = current_cycle + mouse_delays[delay_index];
 621			}
 622		}
 623		break;
 624	case IO_SATURN_KEYBOARD:
 625		if (output & TH) {
 626			//request is over
 627			if (port->device.keyboard.tr_counter >= 10 && port->device.keyboard.read_pos != 0xFF) {
 628				//remove scan code from buffer
 629				port->device.keyboard.read_pos++;
 630				port->device.keyboard.read_pos &= 7;
 631				if (port->device.keyboard.read_pos == port->device.keyboard.write_pos) {
 632					port->device.keyboard.read_pos = 0xFF;
 633				}
 634			}
 635			port->device.keyboard.tr_counter = 0;
 636		} else {
 637			if ((output & TR) != (old_output & TR)) {
 638				port->device.keyboard.tr_counter++;
 639			}
 640		}
 641		break;
 642	case IO_XBAND_KEYBOARD:
 643		if (output & TH) {
 644			//request is over
 645			if (
 646				port->device.keyboard.mode == KB_READ && port->device.keyboard.tr_counter > 6
 647				&& (port->device.keyboard.tr_counter & 1)
 648			) {
 649				if (port->device.keyboard.events[port->device.keyboard.read_pos] & 0xFF00) {
 650					port->device.keyboard.events[port->device.keyboard.read_pos] &= 0xFF;
 651				} else {
 652					port->device.keyboard.read_pos++;
 653					port->device.keyboard.read_pos &= 7;
 654					if (port->device.keyboard.read_pos == port->device.keyboard.write_pos) {
 655						port->device.keyboard.read_pos = 0xFF;
 656					}
 657				}
 658			}
 659			port->device.keyboard.tr_counter = 0;
 660			port->device.keyboard.mode = KB_SETUP;
 661		} else {
 662			if ((output & TR) != (old_output & TR)) {
 663				port->device.keyboard.tr_counter++;
 664				if (port->device.keyboard.tr_counter == 2) {
 665					port->device.keyboard.mode = (output & 0xF) ? KB_READ : KB_WRITE;
 666				} else if (port->device.keyboard.mode == KB_WRITE) {
 667					switch (port->device.keyboard.tr_counter)
 668					{
 669					case 3:
 670						//host writes 0b0001
 671						break;
 672					case 4:
 673						//host writes 0b0000
 674						break;
 675					case 5:
 676						//host writes 0b0000
 677						break;
 678					case 6:
 679						port->device.keyboard.cmd = output << 4;
 680						break;
 681					case 7:
 682						port->device.keyboard.cmd |= output & 0xF;
 683						//TODO: actually do something with the command
 684						break;
 685					}
 686				} else if (
 687					port->device.keyboard.mode == KB_READ && port->device.keyboard.tr_counter > 7
 688					&& !(port->device.keyboard.tr_counter & 1)
 689				) {
 690					
 691					if (port->device.keyboard.events[port->device.keyboard.read_pos] & 0xFF00) {
 692						port->device.keyboard.events[port->device.keyboard.read_pos] &= 0xFF;
 693					} else {
 694						port->device.keyboard.read_pos++;
 695						port->device.keyboard.read_pos &= 7;
 696						if (port->device.keyboard.read_pos == port->device.keyboard.write_pos) {
 697							port->device.keyboard.read_pos = 0xFF;
 698						}
 699					}
 700				}
 701			}
 702		}
 703		break;
 704	case IO_GENERIC:
 705		wait_for_connection(port);
 706		port->input[IO_STATE] = IO_WRITE_PENDING;
 707		service_socket(port);
 708		break;
 709	}
 710	port->output = value;
 711
 712}
 713
 714uint8_t get_scancode_bytes(io_port *port)
 715{
 716	if (port->device.keyboard.read_pos == 0xFF) {
 717		return 0;
 718	}
 719	uint8_t bytes = 0, read_pos = port->device.keyboard.read_pos;
 720	do {
 721		bytes += port->device.keyboard.events[read_pos] & 0xFF00 ? 2 : 1;
 722		read_pos++;
 723		read_pos &= 7;
 724	} while (read_pos != port->device.keyboard.write_pos);
 725	
 726	return bytes;
 727}
 728
 729#define SLOW_RISE_DEVICE (30*7)
 730#define SLOW_RISE_INPUT (12*7)
 731
 732static uint8_t get_output_value(io_port *port, uint32_t current_cycle, uint32_t slow_rise_delay)
 733{
 734	uint8_t output = (port->control | 0x80) & port->output;
 735	for (int i = 0; i < 8; i++)
 736	{
 737		if (!(port->control & 1 << i)) {
 738			if (port->slow_rise_start[i] != CYCLE_NEVER) {
 739				if (current_cycle - port->slow_rise_start[i] >= slow_rise_delay) {
 740					output |= 1 << i;
 741				}
 742			} else {
 743				output |= 1 << i;
 744			}
 745		}
 746	}
 747	return output;
 748}
 749
 750uint8_t io_data_read(io_port * port, uint32_t current_cycle)
 751{
 752	uint8_t output = get_output_value(port, current_cycle, SLOW_RISE_DEVICE);
 753	uint8_t control = port->control | 0x80;
 754	uint8_t th = output & 0x40;
 755	uint8_t input;
 756	uint8_t device_driven;
 757	if (current_cycle - last_poll_cycle > MIN_POLL_INTERVAL) {
 758		process_events();
 759		last_poll_cycle = current_cycle;
 760	}
 761	switch (port->device_type)
 762	{
 763	case IO_GAMEPAD2:
 764		input = ~port->input[GAMEPAD_TH1];
 765		device_driven = 0x3F;
 766		break;
 767	case IO_GAMEPAD3:
 768	{
 769		input = port->input[th ? GAMEPAD_TH1 : GAMEPAD_TH0];
 770		if (!th) {
 771			input |= 0xC;
 772		}
 773		//controller output is logically inverted
 774		input = ~input;
 775		device_driven = 0x3F;
 776		break;
 777	}
 778	case IO_GAMEPAD6:
 779	{
 780		if (current_cycle >= port->device.pad.timeout_cycle) {
 781			port->device.pad.th_counter = 0;
 782		}
 783		/*if (port->input[GAMEPAD_TH0] || port->input[GAMEPAD_TH1]) {
 784			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);
 785		}*/
 786		if (th) {
 787			if (port->device.pad.th_counter == 3) {
 788				input = port->input[GAMEPAD_EXTRA];
 789			} else {
 790				input = port->input[GAMEPAD_TH1];
 791			}
 792		} else {
 793			if (port->device.pad.th_counter == 2) {
 794				input = port->input[GAMEPAD_TH0] | 0xF;
 795			} else if(port->device.pad.th_counter == 3) {
 796				input = port->input[GAMEPAD_TH0]  & 0x30;
 797			} else {
 798				input = port->input[GAMEPAD_TH0] | 0xC;
 799			}
 800		}
 801		//controller output is logically inverted
 802		input = ~input;
 803		device_driven = 0x3F;
 804		break;
 805	}
 806	case IO_MOUSE:
 807	{
 808		mouse_check_ready(port, current_cycle);
 809		uint8_t tr = output & TR;
 810		if (th) {
 811			if (tr) {
 812				input = 0x10;
 813			} else {
 814				input = 0;
 815			}
 816		} else {
 817
 818			int16_t delta_x = port->device.mouse.latched_x - port->device.mouse.last_read_x;
 819			int16_t delta_y = port->device.mouse.last_read_y - port->device.mouse.latched_y;
 820			switch (port->device.mouse.tr_counter)
 821			{
 822			case 0:
 823				input = 0xB;
 824				break;
 825			case 1:
 826			case 2:
 827				input = 0xF;
 828				break;
 829			case 3:
 830				input = 0;
 831				if (delta_y > 255 || delta_y < -255) {
 832					input |= 8;
 833				}
 834				if (delta_x > 255 || delta_x < -255) {
 835					input |= 4;
 836				}
 837				if (delta_y < 0) {
 838					input |= 2;
 839				}
 840				if (delta_x < 0) {
 841					input |= 1;
 842				}
 843				break;
 844			case 4:
 845				input = port->input[0];
 846				break;
 847			case 5:
 848				input = delta_x >> 4 & 0xF;
 849				break;
 850			case 6:
 851				input = delta_x & 0xF;
 852				break;
 853			case 7:
 854				input = delta_y >> 4 & 0xF;
 855				break;
 856			case 8:
 857			default:
 858				input = delta_y & 0xF;
 859				break;
 860			}
 861			input |= ((port->device.mouse.tr_counter & 1) == 0) << 4;
 862		}
 863		device_driven = 0x1F;
 864		break;
 865	}
 866	case IO_SATURN_KEYBOARD:
 867	{
 868		if (th) {
 869			input = 0x11;
 870		} else {
 871			uint16_t code = port->device.keyboard.read_pos == 0xFF ? 0 
 872				: port->device.keyboard.events[port->device.keyboard.read_pos];
 873			switch (port->device.keyboard.tr_counter)
 874			{
 875			case 0:
 876				input = 1;
 877				break;
 878			case 1:
 879				//Saturn peripheral ID
 880				input = 3;
 881				break;
 882			case 2:
 883				//data size
 884				input = 4;
 885				break;
 886			case 3:
 887				//d-pad
 888				//TODO: set these based on keyboard state
 889				input = 0xF;
 890				break;
 891			case 4:
 892				//Start ABC
 893				//TODO: set these based on keyboard state
 894				input = 0xF;
 895				break;
 896			case 5:
 897				//R XYZ
 898				//TODO: set these based on keyboard state
 899				input = 0xF;
 900				break;
 901			case 6:
 902				//L and KBID
 903				//TODO: set L based on keyboard state
 904				input = 0x8;
 905				break;
 906			case 7:
 907				//Capslock, Numlock, Scrolllock
 908				//TODO: set these based on keyboard state
 909				input = 0;
 910				break;
 911			case 8:
 912				input = 6;
 913				if (code & 0xFF00) {
 914					//break
 915					input |= 1;
 916				} else if (code) {
 917					input |= 8;
 918				}
 919				break;
 920			case 9:
 921				input = code >> 4 & 0xF;
 922				break;
 923			case 10:
 924				input = code & 0xF;
 925				break;
 926			case 11:
 927				input = 0;
 928				break;
 929			default:
 930				input = 1;
 931				break;
 932			}
 933			input |= ((port->device.keyboard.tr_counter & 1) == 0) << 4;
 934		}
 935		device_driven = 0x1F;
 936		break;
 937	}
 938	case IO_XBAND_KEYBOARD:
 939	{
 940		if (th) {
 941			input = 0x1C;
 942		} else {
 943			uint8_t size;
 944			if (port->device.keyboard.mode == KB_SETUP || port->device.keyboard.mode == KB_READ) {
 945				switch (port->device.keyboard.tr_counter)
 946				{
 947				case 0:
 948					input = 0x3;
 949					break;
 950				case 1:
 951					input = 0x6;
 952					break;
 953				case 2:
 954					//This is where thoe host indicates a read or write
 955					//presumably, the keyboard only outputs this if the host
 956					//is not already driving the data bus low
 957					input = 0x9;
 958					break;
 959				case 3:
 960					size = get_scancode_bytes(port);
 961					if (size) {
 962						++size;
 963					}
 964					if (size > 15) {
 965						size = 15;
 966					}
 967					input = size;
 968					break;
 969				case 4:
 970				case 5:
 971					//always send packet type 0 for now
 972					input = 0;
 973					break;
 974				default:
 975					if (port->device.keyboard.read_pos == 0xFF) {
 976						//we've run out of bytes
 977						input = 0;
 978					} else if (port->device.keyboard.events[port->device.keyboard.read_pos] & 0xFF00) {
 979						if (port->device.keyboard.tr_counter & 1) {
 980							input = port->device.keyboard.events[port->device.keyboard.read_pos] >> 8 & 0xF;
 981						} else {
 982							input = port->device.keyboard.events[port->device.keyboard.read_pos] >> 12;
 983						}
 984					} else {
 985						if (port->device.keyboard.tr_counter & 1) {
 986							input = port->device.keyboard.events[port->device.keyboard.read_pos] & 0xF;
 987						} else {
 988							input = port->device.keyboard.events[port->device.keyboard.read_pos] >> 4;
 989						}
 990					}
 991					break;
 992				}
 993			} else {
 994				input = 0xF;
 995			}
 996			input |= ((port->device.keyboard.tr_counter & 1) == 0) << 4;
 997		}
 998		//this is not strictly correct at all times, but good enough for now
 999		device_driven = 0x1F;
1000		break;
1001	}
1002	case IO_SEGA_PARALLEL:
1003		if (!th)
1004		{
1005			service_pipe(port);
1006		}
1007		input = port->input[th ? IO_TH1 : IO_TH0];
1008		device_driven = 0x3F;
1009		break;
1010	case IO_GENERIC:
1011		if (port->input[IO_TH0] & 0x80 && port->input[IO_STATE] == IO_WRITTEN)
1012		{
1013			//device requested a blocking read after writes
1014			port->input[IO_STATE] = IO_READ_PENDING;
1015		}
1016		service_socket(port);
1017		input = port->input[IO_TH0];
1018		device_driven = 0x7F;
1019		break;
1020	default:
1021		input = 0;
1022		device_driven = 0;
1023		break;
1024	}
1025	uint8_t value = (input & (~control) & device_driven) | (port->output & control);
1026	//deal with pins that are configured as inputs, but not being actively driven by the device
1027	uint8_t floating = (~device_driven) & (~control);
1028	if (floating) {
1029		value |= get_output_value(port, current_cycle, SLOW_RISE_INPUT) & floating;
1030	}
1031	/*if (port->input[GAMEPAD_TH0] || port->input[GAMEPAD_TH1]) {
1032		printf ("value: %X\n", value);
1033	}*/
1034	return value;
1035}
1036
1037void io_serialize(io_port *port, serialize_buffer *buf)
1038{
1039	save_int8(buf, port->output);
1040	save_int8(buf, port->control);
1041	save_int8(buf, port->serial_out);
1042	save_int8(buf, port->serial_in);
1043	save_int8(buf, port->serial_ctrl);
1044	save_int8(buf, port->device_type);
1045	save_buffer32(buf, port->slow_rise_start, 8);
1046	switch (port->device_type)
1047	{
1048	case IO_GAMEPAD6:
1049		save_int32(buf, port->device.pad.timeout_cycle);
1050		save_int16(buf, port->device.pad.th_counter);
1051		break;
1052	case IO_MOUSE:
1053		save_int32(buf, port->device.mouse.ready_cycle);
1054		save_int16(buf, port->device.mouse.last_read_x);
1055		save_int16(buf, port->device.mouse.last_read_y);
1056		save_int16(buf, port->device.mouse.latched_x);
1057		save_int16(buf, port->device.mouse.latched_y);
1058		save_int8(buf, port->device.mouse.tr_counter);
1059		break;
1060	case IO_SATURN_KEYBOARD:
1061	case IO_XBAND_KEYBOARD:
1062		save_int8(buf, port->device.keyboard.tr_counter);
1063		if (port->device_type == IO_XBAND_KEYBOARD) {
1064			save_int8(buf, port->device.keyboard.mode);
1065			save_int8(buf, port->device.keyboard.cmd);
1066		}
1067		break;
1068	}
1069}
1070
1071void io_deserialize(deserialize_buffer *buf, void *vport)
1072{
1073	io_port *port = vport;
1074	port->output = load_int8(buf);
1075	port->control = load_int8(buf);
1076	port->serial_out = load_int8(buf);
1077	port->serial_in = load_int8(buf);
1078	port->serial_ctrl = load_int8(buf);
1079	uint8_t device_type = load_int8(buf);
1080	if (device_type != port->device_type) {
1081		warning("Loaded save state has a different device type from the current configuration");
1082		return;
1083	}
1084	switch (port->device_type)
1085	{
1086	case IO_GAMEPAD6:
1087		port->device.pad.timeout_cycle = load_int32(buf);
1088		port->device.pad.th_counter = load_int16(buf);
1089		break;
1090	case IO_MOUSE:
1091		port->device.mouse.ready_cycle = load_int32(buf);
1092		port->device.mouse.last_read_x = load_int16(buf);
1093		port->device.mouse.last_read_y = load_int16(buf);
1094		port->device.mouse.latched_x = load_int16(buf);
1095		port->device.mouse.latched_y = load_int16(buf);
1096		port->device.mouse.tr_counter = load_int8(buf);
1097		break;
1098	case IO_SATURN_KEYBOARD:
1099	case IO_XBAND_KEYBOARD:
1100		port->device.keyboard.tr_counter = load_int8(buf);
1101		if (port->device_type == IO_XBAND_KEYBOARD) {
1102			port->device.keyboard.mode = load_int8(buf);
1103			port->device.keyboard.cmd = load_int8(buf);
1104		}
1105		break;
1106	}
1107}