Mercurial > repos > blastem
comparison io.c @ 1348:040c5600e2d9
Implemented slow rise time of IO pins set as inputs, but not driven by device. Fixes input in Decap Attack and possibly other games with buggy controller code
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 08 May 2017 22:31:28 -0700 |
parents | 071e761bcdcf |
children | e587f16e7d3d |
comparison
equal
deleted
inserted
replaced
1347:4c4beb22b042 | 1348:040c5600e2d9 |
---|---|
1504 mouse_check_ready(port, current_cycle); | 1504 mouse_check_ready(port, current_cycle); |
1505 if (port->device.mouse.ready_cycle != CYCLE_NEVER) { | 1505 if (port->device.mouse.ready_cycle != CYCLE_NEVER) { |
1506 port->device.mouse.ready_cycle -= deduction; | 1506 port->device.mouse.ready_cycle -= deduction; |
1507 } | 1507 } |
1508 } | 1508 } |
1509 for (int i = 0; i < 8; i++) | |
1510 { | |
1511 if (port->slow_rise_start[i] != CYCLE_NEVER) { | |
1512 if (port->slow_rise_start[i] >= deduction) { | |
1513 port->slow_rise_start[i] -= deduction; | |
1514 } else { | |
1515 port->slow_rise_start[i] = CYCLE_NEVER; | |
1516 } | |
1517 } | |
1518 } | |
1509 if (last_poll_cycle >= deduction) { | 1519 if (last_poll_cycle >= deduction) { |
1510 last_poll_cycle -= deduction; | 1520 last_poll_cycle -= deduction; |
1511 } else { | 1521 } else { |
1512 last_poll_cycle = 0; | 1522 last_poll_cycle = 0; |
1513 } | 1523 } |
1620 enum { | 1630 enum { |
1621 KB_SETUP, | 1631 KB_SETUP, |
1622 KB_READ, | 1632 KB_READ, |
1623 KB_WRITE | 1633 KB_WRITE |
1624 }; | 1634 }; |
1635 | |
1636 void io_control_write(io_port *port, uint8_t value, uint32_t current_cycle) | |
1637 { | |
1638 uint8_t changes = value ^ port->control; | |
1639 if (changes) { | |
1640 for (int i = 0; i < 8; i++) | |
1641 { | |
1642 if (!(value & 1 << i) && !(port->output & 1 << i)) { | |
1643 //port switched from output to input and the output value was 0 | |
1644 //since there is a weak pull-up on input pins, this will lead | |
1645 //to a slow rise from 0 to 1 if the pin isn't being externally driven | |
1646 port->slow_rise_start[i] = current_cycle; | |
1647 } else { | |
1648 port->slow_rise_start[i] = CYCLE_NEVER; | |
1649 } | |
1650 } | |
1651 port->control = value; | |
1652 } | |
1653 } | |
1625 | 1654 |
1626 void io_data_write(io_port * port, uint8_t value, uint32_t current_cycle) | 1655 void io_data_write(io_port * port, uint8_t value, uint32_t current_cycle) |
1627 { | 1656 { |
1628 uint8_t old_output = (port->control & port->output) | (~port->control & 0xFF); | 1657 uint8_t old_output = (port->control & port->output) | (~port->control & 0xFF); |
1629 uint8_t output = (port->control & value) | (~port->control & 0xFF); | 1658 uint8_t output = (port->control & value) | (~port->control & 0xFF); |
1764 } while (read_pos != port->device.keyboard.write_pos); | 1793 } while (read_pos != port->device.keyboard.write_pos); |
1765 | 1794 |
1766 return bytes; | 1795 return bytes; |
1767 } | 1796 } |
1768 | 1797 |
1798 #define SLOW_RISE_DEVICE (30*7) | |
1799 #define SLOW_RISE_INPUT (12*7) | |
1800 | |
1801 static uint8_t get_output_value(io_port *port, uint32_t current_cycle, uint32_t slow_rise_delay) | |
1802 { | |
1803 uint8_t output = (port->control | 0x80) & port->output; | |
1804 for (int i = 0; i < 8; i++) | |
1805 { | |
1806 if (!(port->control & 1 << i)) { | |
1807 if (port->slow_rise_start[i] != CYCLE_NEVER) { | |
1808 if (current_cycle - port->slow_rise_start[i] >= slow_rise_delay) { | |
1809 output |= 1 << i; | |
1810 } | |
1811 } else { | |
1812 output |= 1 << i; | |
1813 } | |
1814 } | |
1815 } | |
1816 return output; | |
1817 } | |
1818 | |
1769 uint8_t io_data_read(io_port * port, uint32_t current_cycle) | 1819 uint8_t io_data_read(io_port * port, uint32_t current_cycle) |
1770 { | 1820 { |
1821 uint8_t output = get_output_value(port, current_cycle, SLOW_RISE_DEVICE); | |
1771 uint8_t control = port->control | 0x80; | 1822 uint8_t control = port->control | 0x80; |
1772 uint8_t output = (control & port->output) | (~control & 0xFF); | |
1773 uint8_t th = output & 0x40; | 1823 uint8_t th = output & 0x40; |
1774 uint8_t input; | 1824 uint8_t input; |
1825 uint8_t device_driven; | |
1775 if (current_cycle - last_poll_cycle > MIN_POLL_INTERVAL) { | 1826 if (current_cycle - last_poll_cycle > MIN_POLL_INTERVAL) { |
1776 process_events(); | 1827 process_events(); |
1777 last_poll_cycle = current_cycle; | 1828 last_poll_cycle = current_cycle; |
1778 } | 1829 } |
1779 switch (port->device_type) | 1830 switch (port->device_type) |
1787 if (!th) { | 1838 if (!th) { |
1788 input |= 0xC; | 1839 input |= 0xC; |
1789 } | 1840 } |
1790 //controller output is logically inverted | 1841 //controller output is logically inverted |
1791 input = ~input; | 1842 input = ~input; |
1843 device_driven = 0x3F; | |
1792 break; | 1844 break; |
1793 } | 1845 } |
1794 case IO_GAMEPAD6: | 1846 case IO_GAMEPAD6: |
1795 { | 1847 { |
1796 if (current_cycle >= port->device.pad.timeout_cycle) { | 1848 if (current_cycle >= port->device.pad.timeout_cycle) { |
1814 input = port->input[GAMEPAD_TH0] | 0xC; | 1866 input = port->input[GAMEPAD_TH0] | 0xC; |
1815 } | 1867 } |
1816 } | 1868 } |
1817 //controller output is logically inverted | 1869 //controller output is logically inverted |
1818 input = ~input; | 1870 input = ~input; |
1871 device_driven = 0x3F; | |
1819 break; | 1872 break; |
1820 } | 1873 } |
1821 case IO_MOUSE: | 1874 case IO_MOUSE: |
1822 { | 1875 { |
1823 mouse_check_ready(port, current_cycle); | 1876 mouse_check_ready(port, current_cycle); |
1873 input = delta_y & 0xF; | 1926 input = delta_y & 0xF; |
1874 break; | 1927 break; |
1875 } | 1928 } |
1876 input |= ((port->device.mouse.tr_counter & 1) == 0) << 4; | 1929 input |= ((port->device.mouse.tr_counter & 1) == 0) << 4; |
1877 } | 1930 } |
1931 device_driven = 0x1F; | |
1878 break; | 1932 break; |
1879 } | 1933 } |
1880 case IO_SATURN_KEYBOARD: | 1934 case IO_SATURN_KEYBOARD: |
1881 { | 1935 { |
1882 if (th) { | 1936 if (th) { |
1945 input = 1; | 1999 input = 1; |
1946 break; | 2000 break; |
1947 } | 2001 } |
1948 input |= ((port->device.keyboard.tr_counter & 1) == 0) << 4; | 2002 input |= ((port->device.keyboard.tr_counter & 1) == 0) << 4; |
1949 } | 2003 } |
2004 device_driven = 0x1F; | |
1950 break; | 2005 break; |
1951 } | 2006 } |
1952 case IO_XBAND_KEYBOARD: | 2007 case IO_XBAND_KEYBOARD: |
1953 { | 2008 { |
1954 if (th) { | 2009 if (th) { |
2006 } | 2061 } |
2007 } else { | 2062 } else { |
2008 input = 0xF; | 2063 input = 0xF; |
2009 } | 2064 } |
2010 input |= ((port->device.keyboard.tr_counter & 1) == 0) << 4; | 2065 input |= ((port->device.keyboard.tr_counter & 1) == 0) << 4; |
2066 //this is not strictly correct at all times, but good enough for now | |
2067 device_driven = 0x1F; | |
2011 } | 2068 } |
2012 break; | 2069 break; |
2013 } | 2070 } |
2014 #ifndef _WIN32 | 2071 #ifndef _WIN32 |
2015 case IO_SEGA_PARALLEL: | 2072 case IO_SEGA_PARALLEL: |
2016 if (!th) | 2073 if (!th) |
2017 { | 2074 { |
2018 service_pipe(port); | 2075 service_pipe(port); |
2019 } | 2076 } |
2020 input = port->input[th ? IO_TH1 : IO_TH0]; | 2077 input = port->input[th ? IO_TH1 : IO_TH0]; |
2078 device_driven = 0x3F; | |
2021 break; | 2079 break; |
2022 case IO_GENERIC: | 2080 case IO_GENERIC: |
2023 if (port->input[IO_TH0] & 0x80 && port->input[IO_STATE] == IO_WRITTEN) | 2081 if (port->input[IO_TH0] & 0x80 && port->input[IO_STATE] == IO_WRITTEN) |
2024 { | 2082 { |
2025 //device requested a blocking read after writes | 2083 //device requested a blocking read after writes |
2026 port->input[IO_STATE] = IO_READ_PENDING; | 2084 port->input[IO_STATE] = IO_READ_PENDING; |
2027 } | 2085 } |
2028 service_socket(port); | 2086 service_socket(port); |
2029 input = port->input[IO_TH0]; | 2087 input = port->input[IO_TH0]; |
2088 device_driven = 0x7F; | |
2030 break; | 2089 break; |
2031 #endif | 2090 #endif |
2032 default: | 2091 default: |
2033 input = 0xFF; | 2092 input = 0; |
2034 break; | 2093 device_driven = 0; |
2035 } | 2094 break; |
2036 uint8_t value = (input & (~control)) | (port->output & control); | 2095 } |
2096 uint8_t value = (input & (~control) & device_driven) | (port->output & control); | |
2097 //deal with pins that are configured as inputs, but not being actively driven by the device | |
2098 uint8_t floating = (~device_driven) & (~control); | |
2099 if (floating) { | |
2100 value |= get_output_value(port, current_cycle, SLOW_RISE_INPUT) & floating; | |
2101 } | |
2037 /*if (port->input[GAMEPAD_TH0] || port->input[GAMEPAD_TH1]) { | 2102 /*if (port->input[GAMEPAD_TH0] || port->input[GAMEPAD_TH1]) { |
2038 printf ("value: %X\n", value); | 2103 printf ("value: %X\n", value); |
2039 }*/ | 2104 }*/ |
2040 return value; | 2105 return value; |
2041 } | 2106 } |