From 75e313ab6c0a9e5199c9481d3580e819f30f0e56 Mon Sep 17 00:00:00 2001 From: arbee Date: Sun, 23 Jun 2024 19:26:27 -0400 Subject: apple/adbmodem.cpp: Fix for corrupted data transfer from the VIA to the PIC. [R. Belmont] - This caused the mouse button to randomly press and release, especially on faster machines --- src/mame/apple/adbmodem.cpp | 60 +++++++++++++++++++++++++++++++++++---------- src/mame/apple/adbmodem.h | 23 +++++++++-------- 2 files changed, 58 insertions(+), 25 deletions(-) diff --git a/src/mame/apple/adbmodem.cpp b/src/mame/apple/adbmodem.cpp index 1e310864a34..d90192d5e3a 100644 --- a/src/mame/apple/adbmodem.cpp +++ b/src/mame/apple/adbmodem.cpp @@ -102,7 +102,16 @@ adbmodem_device::adbmodem_device(const machine_config &mconfig, const char *tag, write_via_clock(*this), write_via_data(*this), write_irq(*this), - m_maincpu(*this, "adbmodem") + m_maincpu(*this, "adbmodem"), + m_via_data(0), + m_via_clock(0), + m_last_adb(0), + m_via_state(0), + m_last_adb_time(0), + m_adb_in(false), + m_reset_line(0), + m_adb_dtime(0), + m_last_via_clock(1) #if USE_BUS_ADB , m_adb_connector{{*this, "adb1"}, {*this, finder_base::DUMMY_TAG}} #endif @@ -127,10 +136,10 @@ void adbmodem_device::device_start() } #endif - save_item(NAME(via_data)); - save_item(NAME(via_clock)); - save_item(NAME(adb_in)); - save_item(NAME(reset_line)); + save_item(NAME(m_via_data)); + save_item(NAME(m_via_clock)); + save_item(NAME(m_adb_in)); + save_item(NAME(m_reset_line)); save_item(NAME(m_adb_dtime)); #if USE_BUS_ADB @@ -152,17 +161,18 @@ void adbmodem_device::device_reset() m_adb_device_poweron[0] = m_adb_device_poweron[1] = true; #endif - adb_in = true; // line is pulled up to +5v, so nothing plugged in would read as "1" - reset_line = 0; - via_data = 0; - via_clock = 0; - last_adb_time = m_maincpu->total_cycles(); - last_adb = 0; + m_adb_in = true; // line is pulled up to +5v, so nothing plugged in would read as "1" + m_reset_line = 0; + m_via_data = 0; + m_via_clock = 0; + m_last_adb_time = m_maincpu->total_cycles(); + m_last_adb = 0; + m_last_via_clock = 1; } u8 adbmodem_device::porta_r() { - return (m_via_state & 3) | (adb_in << 3); + return (m_via_state & 3) | (m_adb_in << 3); } void adbmodem_device::porta_w(u8 data) @@ -172,13 +182,37 @@ void adbmodem_device::porta_w(u8 data) u8 adbmodem_device::portb_r() { - return (via_data << 3); + return (m_via_data << 3); } void adbmodem_device::portb_w(u8 data) { + m_last_via_clock = BIT(data, 2); write_via_data(BIT(data, 3)); write_via_clock(BIT(data, 2)); write_irq(BIT(data, 4) ^ 1); } +void adbmodem_device::set_via_data(u8 dat) +{ + /* + There is a race condition we sometimes lose on fast CPUs like the IIci where + the final bit shifts out of the VIA and the 68k writes the VIA ACR (causing the + data line to go high) before the PIC has sampled it to get the final bit state. + This manifested as ADB TALK mouse commands going to register 1 instead of 0, which + due to implementation details of macadb returned 00 00 for no mouse data available + instead of 80 80, and therefore the mouse button state in MacOS went nuts. + + We solve this by only accepting ADB data line state changes when the last VIA clock + we wrote was 0; the VIA is configured with this device to transmit on the falling + edge of the clock. + + Thanks to Tashtari for his extensively commmented disassembly and port of this PIC + program to the modern PIC16F87 and PIC16F88, which are pin-compatible with the + PIC1654S originally used. https://github.com/lampmerchant/macseadb88 + */ + if (!m_last_via_clock) + { + m_via_data = dat; + } +} diff --git a/src/mame/apple/adbmodem.h b/src/mame/apple/adbmodem.h index d7efd94ffbe..f605a09c716 100644 --- a/src/mame/apple/adbmodem.h +++ b/src/mame/apple/adbmodem.h @@ -38,10 +38,8 @@ public: #endif // interface routines - u8 get_via_data() { return via_data; } - void set_via_data(uint8_t dat) { via_data = dat; } - u8 get_via_clock() { return via_clock; } - void set_adb_line(int linestate) { adb_in = (linestate == ASSERT_LINE) ? true : false; } + void set_via_data(u8 dat); + void set_adb_line(int linestate) { m_adb_in = (linestate == ASSERT_LINE) ? true : false; } void set_via_state(u8 state) { m_via_state = state; } int rom_offset; @@ -72,14 +70,15 @@ private: u8 portb_r(); void portb_w(u8 data); - u8 via_data = 0; - u8 via_clock = 0; - u8 last_adb = 0; - u8 m_via_state = 0; - u64 last_adb_time = 0; - bool adb_in = false; - int reset_line = 0; - int m_adb_dtime = 0; + u8 m_via_data; + u8 m_via_clock; + u8 m_last_adb; + u8 m_via_state; + u64 m_last_adb_time; + bool m_adb_in; + int m_reset_line; + int m_adb_dtime; + int m_last_via_clock; #if USE_BUS_ADB optional_device m_adb_connector[2]; -- cgit v1.2.3