# HG changeset patch # User Michael Pavone # Date 1449458974 28800 # Node ID 599e2861f484510b10dadc2e6cb07193acfc7de7 # Parent 73732ae76fa8a5f3abdc295c8accf4487bf93227 Rough emulation of mouse response delays when TR is toggled. Latch current mouse value rather than delta. Some other IO cleanup/fixes diff -r 73732ae76fa8 -r 599e2861f484 io.c --- a/io.c Sun Dec 06 15:42:36 2015 -0800 +++ b/io.c Sun Dec 06 19:29:34 2015 -0800 @@ -20,6 +20,8 @@ #include "render.h" #include "util.h" +#define CYCLE_NEVER 0xFFFFFFFF + const char * device_type_names[] = { "3-button gamepad", "6-button gamepad", @@ -607,6 +609,9 @@ port->device.mouse.last_read_y = 0; port->device.mouse.cur_x = 0; port->device.mouse.cur_y = 0; + port->device.mouse.latched_x = 0; + port->device.mouse.latched_y = 0; + port->device.mouse.ready_cycle = CYCLE_NEVER; port->device.mouse.tr_counter = 0; } else if(!strcmp(device_type, "sega_parallel")) { port->device_type = IO_SEGA_PARALLEL; @@ -998,6 +1003,18 @@ #define TR 0x20 #define TH_TIMEOUT 56000 +void mouse_check_ready(io_port *port, uint32_t current_cycle) +{ + if (current_cycle >= port->device.mouse.ready_cycle) { + port->device.mouse.tr_counter++; + port->device.mouse.ready_cycle = CYCLE_NEVER; + if (port->device.mouse.tr_counter == 3) { + port->device.mouse.latched_x = port->device.mouse.cur_x; + port->device.mouse.latched_y = port->device.mouse.cur_y; + } + } +} + void io_adjust_cycles(io_port * port, uint32_t current_cycle, uint32_t deduction) { /*uint8_t control = pad->control | 0x80; @@ -1013,6 +1030,11 @@ } else { port->device.pad.timeout_cycle -= deduction; } + } else if (port->device_type == IO_MOUSE) { + mouse_check_ready(port, current_cycle); + if (port->device.mouse.ready_cycle != CYCLE_NEVER) { + port->device.mouse.ready_cycle -= deduction; + } } } @@ -1118,46 +1140,53 @@ } #endif +const int mouse_delays[] = {112*7, 120*7, 96*7, 132*7, 104*7, 96*7, 112*7, 96*7}; + void io_data_write(io_port * port, uint8_t value, uint32_t current_cycle) { + uint8_t old_output = (port->control & port->output) | (~port->control & 0xFF); + uint8_t output = (port->control & value) | (~port->control & 0xFF); switch (port->device_type) { case IO_GAMEPAD6: - if (port->control & TH) { - //check if TH has changed - if ((port->output & TH) ^ (value & TH)) { - if (current_cycle >= port->device.pad.timeout_cycle) { - port->device.pad.th_counter = 0; - } - if (!(value & TH)) { - port->device.pad.th_counter++; - } - port->device.pad.timeout_cycle = current_cycle + TH_TIMEOUT; + //check if TH has changed + if ((old_output & TH) ^ (output & TH)) { + if (current_cycle >= port->device.pad.timeout_cycle) { + port->device.pad.th_counter = 0; + } + if (!(output & TH)) { + port->device.pad.th_counter++; + } + port->device.pad.timeout_cycle = current_cycle + TH_TIMEOUT; + } + break; + case IO_MOUSE: + mouse_check_ready(port, current_cycle); + if (output & TH) { + //request is over or mouse is being reset + if (port->device.mouse.tr_counter) { + //request is over + port->device.mouse.last_read_x = port->device.mouse.latched_x; + port->device.mouse.last_read_y = port->device.mouse.latched_y; + } + port->device.mouse.tr_counter = 0; + port->device.mouse.ready_cycle = CYCLE_NEVER; + } else { + if ((output & TR) != (old_output & TR)) { + int delay_index = port->device.mouse.tr_counter >= sizeof(mouse_delays) ? sizeof(mouse_delays)-1 : port->device.mouse.tr_counter; + port->device.mouse.ready_cycle = current_cycle + mouse_delays[delay_index]; } } - port->output = value; - break; - case IO_MOUSE: - if ((port->control & (TH|TR)) == (TH|TR)) { - if (!(value & TH) && (value & TR) != (port->output & TR)) { - port->device.mouse.tr_counter++; - } - } else { - port->device.mouse.tr_counter = 0; - } - port->output = value; break; #ifndef _WIN32 case IO_GENERIC: wait_for_connection(port); port->input[IO_STATE] = IO_WRITE_PENDING; - port->output = value; service_socket(port); break; #endif - default: - port->output = value; } + port->output = value; } @@ -1208,6 +1237,7 @@ } case IO_MOUSE: { + mouse_check_ready(port, current_cycle); uint8_t tr = output & TR; if (th) { if (tr) { @@ -1216,6 +1246,9 @@ input = 0; } } else { + + int16_t delta_x = port->device.mouse.latched_x - port->device.mouse.last_read_x; + int16_t delta_y = port->device.mouse.last_read_y - port->device.mouse.latched_y; switch (port->device.mouse.tr_counter) { case 0: @@ -1227,20 +1260,16 @@ break; case 3: input = 0; - //it would be unfortunate if our event handler updated cur_x or cur_y in the middle - //of the mouse poll sequence, so we save the delta here - port->device.mouse.delta_x = port->device.mouse.cur_x - port->device.mouse.last_read_x; - port->device.mouse.delta_y = port->device.mouse.last_read_y - port->device.mouse.cur_y; - if (port->device.mouse.delta_y > 255 || port->device.mouse.delta_y < -255) { + if (delta_y > 255 || delta_y < -255) { input |= 8; } - if (port->device.mouse.delta_x > 255 || port->device.mouse.delta_x < -255) { + if (delta_x > 255 || delta_x < -255) { input |= 4; } - if (port->device.mouse.delta_y < 0) { + if (delta_y < 0) { input |= 2; } - if (port->device.mouse.delta_x < 0) { + if (delta_x < 0) { input |= 1; } break; @@ -1248,26 +1277,20 @@ input = port->input[0]; break; case 5: - input = port->device.mouse.delta_x >> 4 & 0xF; + input = delta_x >> 4 & 0xF; break; case 6: - input = port->device.mouse.delta_x & 0xF; + input = delta_x & 0xF; break; case 7: - input = port->device.mouse.delta_y >> 4 & 0xF; + input = delta_y >> 4 & 0xF; break; case 8: - input = port->device.mouse.delta_y & 0xF; - //need to figure out when this actually happens - port->device.mouse.last_read_x = port->device.mouse.cur_x; - port->device.mouse.last_read_y = port->device.mouse.cur_y; - break; default: - //need to test what happens here - input = 0; + input = delta_y & 0xF; break; } - input |= tr >> 1; + input |= ((port->device.mouse.tr_counter & 1) == 0) << 4; } break; } diff -r 73732ae76fa8 -r 599e2861f484 io.h --- a/io.h Sun Dec 06 15:42:36 2015 -0800 +++ b/io.h Sun Dec 06 19:29:34 2015 -0800 @@ -34,12 +34,13 @@ int listen_fd; } stream; struct { + uint32_t ready_cycle; uint16_t last_read_x; uint16_t last_read_y; uint16_t cur_x; uint16_t cur_y; - int16_t delta_x; - int16_t delta_y; + uint16_t latched_x; + uint16_t latched_y; uint8_t tr_counter; uint8_t mouse_num; } mouse;