changeset 2661:462e43f54abf

Properly emulate extra TH transitions due to direction changes for 6-button controllers. Breaks Golden Axe II input the same as hardware with a 6-button controller
author Michael Pavone <pavone@retrodev.com>
date Wed, 05 Mar 2025 22:20:20 -0800
parents 9a5e627c1b1f
children 5e2d41f0d2ba
files io.c
diffstat 1 files changed, 39 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/io.c	Tue Mar 04 00:42:14 2025 -0800
+++ b/io.c	Wed Mar 05 22:20:20 2025 -0800
@@ -559,6 +559,7 @@
 		if (!(port->control & 1 << i)) {
 			if (port->slow_rise_start[i] != CYCLE_NEVER) {
 				if (current_cycle - port->slow_rise_start[i] >= slow_rise_delay) {
+					port->slow_rise_start[i] = CYCLE_NEVER;
 					output |= 1 << i;
 				}
 			} else {
@@ -1260,6 +1261,20 @@
 {
 	uint8_t changes = value ^ port->control;
 	if (changes) {
+		uint8_t old_output;
+		if (port->device_type == IO_GAMEPAD6) {
+			//slow IO rise could have caused a TH transition
+			if (port->slow_rise_start[6] != CYCLE_NEVER && current_cycle - port->slow_rise_start[6] >= SLOW_RISE_DEVICE) {
+				uint32_t rise_cycle = port->slow_rise_start[6] + SLOW_RISE_DEVICE;
+				if (rise_cycle >= port->device.pad.timeout_cycle) {
+					port->device.pad.th_counter = 0;
+				}
+				
+				port->device.pad.th_counter++;
+				port->device.pad.timeout_cycle = rise_cycle + TH_TIMEOUT;
+			}
+			old_output = get_output_value(port, current_cycle, SLOW_RISE_DEVICE);
+		}
 		for (int i = 0; i < 8; i++)
 		{
 			if (!(value & 1 << i) && !(port->output & 1 << i)) {
@@ -1272,11 +1287,35 @@
 			}
 		}
 		port->control = value;
+		if (port->device_type == IO_GAMEPAD6) {
+			uint8_t output = get_output_value(port, current_cycle, SLOW_RISE_DEVICE);
+			if (TH & (old_output ^ output)) {
+				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;
+			}
+		}
 	}
 }
 
 void io_data_write(io_port * port, uint8_t value, uint32_t current_cycle)
 {
+	if (port->device_type == IO_GAMEPAD6) {
+		//slow IO rise could have caused a TH transition
+		if (port->slow_rise_start[6] != CYCLE_NEVER && current_cycle - port->slow_rise_start[6] >= SLOW_RISE_DEVICE) {
+			uint32_t rise_cycle = port->slow_rise_start[6] + SLOW_RISE_DEVICE;
+			if (rise_cycle >= port->device.pad.timeout_cycle) {
+				port->device.pad.th_counter = 0;
+			}
+			
+			port->device.pad.th_counter++;
+			port->device.pad.timeout_cycle = rise_cycle + TH_TIMEOUT;
+		}
+	}
 	uint8_t old_output = get_output_value(port, current_cycle, SLOW_RISE_DEVICE);
 	port->output = value;
 	uint8_t output = get_output_value(port, current_cycle, SLOW_RISE_DEVICE);