comparison io.c @ 912:599e2861f484

Rough emulation of mouse response delays when TR is toggled. Latch current mouse value rather than delta. Some other IO cleanup/fixes
author Michael Pavone <pavone@retrodev.com>
date Sun, 06 Dec 2015 19:29:34 -0800
parents 73732ae76fa8
children a5a51465f8b0
comparison
equal deleted inserted replaced
911:73732ae76fa8 912:599e2861f484
17 17
18 #include "io.h" 18 #include "io.h"
19 #include "blastem.h" 19 #include "blastem.h"
20 #include "render.h" 20 #include "render.h"
21 #include "util.h" 21 #include "util.h"
22
23 #define CYCLE_NEVER 0xFFFFFFFF
22 24
23 const char * device_type_names[] = { 25 const char * device_type_names[] = {
24 "3-button gamepad", 26 "3-button gamepad",
25 "6-button gamepad", 27 "6-button gamepad",
26 "Mega Mouse", 28 "Mega Mouse",
605 port->device.mouse.mouse_num = device_type[mouse_len+1] - '1'; 607 port->device.mouse.mouse_num = device_type[mouse_len+1] - '1';
606 port->device.mouse.last_read_x = 0; 608 port->device.mouse.last_read_x = 0;
607 port->device.mouse.last_read_y = 0; 609 port->device.mouse.last_read_y = 0;
608 port->device.mouse.cur_x = 0; 610 port->device.mouse.cur_x = 0;
609 port->device.mouse.cur_y = 0; 611 port->device.mouse.cur_y = 0;
612 port->device.mouse.latched_x = 0;
613 port->device.mouse.latched_y = 0;
614 port->device.mouse.ready_cycle = CYCLE_NEVER;
610 port->device.mouse.tr_counter = 0; 615 port->device.mouse.tr_counter = 0;
611 } else if(!strcmp(device_type, "sega_parallel")) { 616 } else if(!strcmp(device_type, "sega_parallel")) {
612 port->device_type = IO_SEGA_PARALLEL; 617 port->device_type = IO_SEGA_PARALLEL;
613 port->device.stream.data_fd = -1; 618 port->device.stream.data_fd = -1;
614 port->device.stream.listen_fd = -1; 619 port->device.stream.listen_fd = -1;
996 1001
997 #define TH 0x40 1002 #define TH 0x40
998 #define TR 0x20 1003 #define TR 0x20
999 #define TH_TIMEOUT 56000 1004 #define TH_TIMEOUT 56000
1000 1005
1006 void mouse_check_ready(io_port *port, uint32_t current_cycle)
1007 {
1008 if (current_cycle >= port->device.mouse.ready_cycle) {
1009 port->device.mouse.tr_counter++;
1010 port->device.mouse.ready_cycle = CYCLE_NEVER;
1011 if (port->device.mouse.tr_counter == 3) {
1012 port->device.mouse.latched_x = port->device.mouse.cur_x;
1013 port->device.mouse.latched_y = port->device.mouse.cur_y;
1014 }
1015 }
1016 }
1017
1001 void io_adjust_cycles(io_port * port, uint32_t current_cycle, uint32_t deduction) 1018 void io_adjust_cycles(io_port * port, uint32_t current_cycle, uint32_t deduction)
1002 { 1019 {
1003 /*uint8_t control = pad->control | 0x80; 1020 /*uint8_t control = pad->control | 0x80;
1004 uint8_t th = control & pad->output; 1021 uint8_t th = control & pad->output;
1005 if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) { 1022 if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) {
1010 if (current_cycle >= port->device.pad.timeout_cycle) 1027 if (current_cycle >= port->device.pad.timeout_cycle)
1011 { 1028 {
1012 port->device.pad.th_counter = 0; 1029 port->device.pad.th_counter = 0;
1013 } else { 1030 } else {
1014 port->device.pad.timeout_cycle -= deduction; 1031 port->device.pad.timeout_cycle -= deduction;
1032 }
1033 } else if (port->device_type == IO_MOUSE) {
1034 mouse_check_ready(port, current_cycle);
1035 if (port->device.mouse.ready_cycle != CYCLE_NEVER) {
1036 port->device.mouse.ready_cycle -= deduction;
1015 } 1037 }
1016 } 1038 }
1017 } 1039 }
1018 1040
1019 #ifndef _WIN32 1041 #ifndef _WIN32
1116 } 1138 }
1117 } 1139 }
1118 } 1140 }
1119 #endif 1141 #endif
1120 1142
1143 const int mouse_delays[] = {112*7, 120*7, 96*7, 132*7, 104*7, 96*7, 112*7, 96*7};
1144
1121 void io_data_write(io_port * port, uint8_t value, uint32_t current_cycle) 1145 void io_data_write(io_port * port, uint8_t value, uint32_t current_cycle)
1122 { 1146 {
1147 uint8_t old_output = (port->control & port->output) | (~port->control & 0xFF);
1148 uint8_t output = (port->control & value) | (~port->control & 0xFF);
1123 switch (port->device_type) 1149 switch (port->device_type)
1124 { 1150 {
1125 case IO_GAMEPAD6: 1151 case IO_GAMEPAD6:
1126 if (port->control & TH) { 1152 //check if TH has changed
1127 //check if TH has changed 1153 if ((old_output & TH) ^ (output & TH)) {
1128 if ((port->output & TH) ^ (value & TH)) { 1154 if (current_cycle >= port->device.pad.timeout_cycle) {
1129 if (current_cycle >= port->device.pad.timeout_cycle) { 1155 port->device.pad.th_counter = 0;
1130 port->device.pad.th_counter = 0; 1156 }
1131 } 1157 if (!(output & TH)) {
1132 if (!(value & TH)) { 1158 port->device.pad.th_counter++;
1133 port->device.pad.th_counter++; 1159 }
1134 } 1160 port->device.pad.timeout_cycle = current_cycle + TH_TIMEOUT;
1135 port->device.pad.timeout_cycle = current_cycle + TH_TIMEOUT; 1161 }
1136 }
1137 }
1138 port->output = value;
1139 break; 1162 break;
1140 case IO_MOUSE: 1163 case IO_MOUSE:
1141 if ((port->control & (TH|TR)) == (TH|TR)) { 1164 mouse_check_ready(port, current_cycle);
1142 if (!(value & TH) && (value & TR) != (port->output & TR)) { 1165 if (output & TH) {
1143 port->device.mouse.tr_counter++; 1166 //request is over or mouse is being reset
1144 } 1167 if (port->device.mouse.tr_counter) {
1168 //request is over
1169 port->device.mouse.last_read_x = port->device.mouse.latched_x;
1170 port->device.mouse.last_read_y = port->device.mouse.latched_y;
1171 }
1172 port->device.mouse.tr_counter = 0;
1173 port->device.mouse.ready_cycle = CYCLE_NEVER;
1145 } else { 1174 } else {
1146 port->device.mouse.tr_counter = 0; 1175 if ((output & TR) != (old_output & TR)) {
1147 } 1176 int delay_index = port->device.mouse.tr_counter >= sizeof(mouse_delays) ? sizeof(mouse_delays)-1 : port->device.mouse.tr_counter;
1148 port->output = value; 1177 port->device.mouse.ready_cycle = current_cycle + mouse_delays[delay_index];
1178 }
1179 }
1149 break; 1180 break;
1150 #ifndef _WIN32 1181 #ifndef _WIN32
1151 case IO_GENERIC: 1182 case IO_GENERIC:
1152 wait_for_connection(port); 1183 wait_for_connection(port);
1153 port->input[IO_STATE] = IO_WRITE_PENDING; 1184 port->input[IO_STATE] = IO_WRITE_PENDING;
1154 port->output = value;
1155 service_socket(port); 1185 service_socket(port);
1156 break; 1186 break;
1157 #endif 1187 #endif
1158 default: 1188 }
1159 port->output = value; 1189 port->output = value;
1160 }
1161 1190
1162 } 1191 }
1163 1192
1164 uint8_t io_data_read(io_port * port, uint32_t current_cycle) 1193 uint8_t io_data_read(io_port * port, uint32_t current_cycle)
1165 { 1194 {
1206 input = ~input; 1235 input = ~input;
1207 break; 1236 break;
1208 } 1237 }
1209 case IO_MOUSE: 1238 case IO_MOUSE:
1210 { 1239 {
1240 mouse_check_ready(port, current_cycle);
1211 uint8_t tr = output & TR; 1241 uint8_t tr = output & TR;
1212 if (th) { 1242 if (th) {
1213 if (tr) { 1243 if (tr) {
1214 input = 0x10; 1244 input = 0x10;
1215 } else { 1245 } else {
1216 input = 0; 1246 input = 0;
1217 } 1247 }
1218 } else { 1248 } else {
1249
1250 int16_t delta_x = port->device.mouse.latched_x - port->device.mouse.last_read_x;
1251 int16_t delta_y = port->device.mouse.last_read_y - port->device.mouse.latched_y;
1219 switch (port->device.mouse.tr_counter) 1252 switch (port->device.mouse.tr_counter)
1220 { 1253 {
1221 case 0: 1254 case 0:
1222 input = 0xB; 1255 input = 0xB;
1223 break; 1256 break;
1225 case 2: 1258 case 2:
1226 input = 0xF; 1259 input = 0xF;
1227 break; 1260 break;
1228 case 3: 1261 case 3:
1229 input = 0; 1262 input = 0;
1230 //it would be unfortunate if our event handler updated cur_x or cur_y in the middle 1263 if (delta_y > 255 || delta_y < -255) {
1231 //of the mouse poll sequence, so we save the delta here
1232 port->device.mouse.delta_x = port->device.mouse.cur_x - port->device.mouse.last_read_x;
1233 port->device.mouse.delta_y = port->device.mouse.last_read_y - port->device.mouse.cur_y;
1234 if (port->device.mouse.delta_y > 255 || port->device.mouse.delta_y < -255) {
1235 input |= 8; 1264 input |= 8;
1236 } 1265 }
1237 if (port->device.mouse.delta_x > 255 || port->device.mouse.delta_x < -255) { 1266 if (delta_x > 255 || delta_x < -255) {
1238 input |= 4; 1267 input |= 4;
1239 } 1268 }
1240 if (port->device.mouse.delta_y < 0) { 1269 if (delta_y < 0) {
1241 input |= 2; 1270 input |= 2;
1242 } 1271 }
1243 if (port->device.mouse.delta_x < 0) { 1272 if (delta_x < 0) {
1244 input |= 1; 1273 input |= 1;
1245 } 1274 }
1246 break; 1275 break;
1247 case 4: 1276 case 4:
1248 input = port->input[0]; 1277 input = port->input[0];
1249 break; 1278 break;
1250 case 5: 1279 case 5:
1251 input = port->device.mouse.delta_x >> 4 & 0xF; 1280 input = delta_x >> 4 & 0xF;
1252 break; 1281 break;
1253 case 6: 1282 case 6:
1254 input = port->device.mouse.delta_x & 0xF; 1283 input = delta_x & 0xF;
1255 break; 1284 break;
1256 case 7: 1285 case 7:
1257 input = port->device.mouse.delta_y >> 4 & 0xF; 1286 input = delta_y >> 4 & 0xF;
1258 break; 1287 break;
1259 case 8: 1288 case 8:
1260 input = port->device.mouse.delta_y & 0xF; 1289 default:
1261 //need to figure out when this actually happens 1290 input = delta_y & 0xF;
1262 port->device.mouse.last_read_x = port->device.mouse.cur_x;
1263 port->device.mouse.last_read_y = port->device.mouse.cur_y;
1264 break; 1291 break;
1265 default: 1292 }
1266 //need to test what happens here 1293 input |= ((port->device.mouse.tr_counter & 1) == 0) << 4;
1267 input = 0;
1268 break;
1269 }
1270 input |= tr >> 1;
1271 } 1294 }
1272 break; 1295 break;
1273 } 1296 }
1274 #ifndef _WIN32 1297 #ifndef _WIN32
1275 case IO_SEGA_PARALLEL: 1298 case IO_SEGA_PARALLEL: