From 04e529dcb54753b885edfda0455bf2fb1a278dbc Mon Sep 17 00:00:00 2001 From: arbee Date: Tue, 22 Nov 2022 22:47:33 -0500 Subject: mac: welcome back ADB full HLE for the Mac IIs so SCSI works again. Sigh. [R. Belmont] --- src/mame/apple/mac.cpp | 18 +++ src/mame/apple/mac.h | 2 + src/mame/apple/mac_m.cpp | 21 +++ src/mame/apple/macadb.cpp | 371 ++++++++++++++++++++++++++++++++++------------ src/mame/apple/macadb.h | 17 ++- 5 files changed, 334 insertions(+), 95 deletions(-) diff --git a/src/mame/apple/mac.cpp b/src/mame/apple/mac.cpp index f57b263a907..8cd53fbc440 100644 --- a/src/mame/apple/mac.cpp +++ b/src/mame/apple/mac.cpp @@ -622,6 +622,7 @@ void mac_state::macii(machine_config &config, bool cpu, asc_device::asc_type asc add_via1_adb(config, true); add_via2(config); +#if MACII_USE_ADBMODEM ADBMODEM(config, m_adbmodem, C7M); m_adbmodem->via_clock_callback().set(m_via1, FUNC(via6522_device::write_cb1)); m_adbmodem->via_data_callback().set(m_via1, FUNC(via6522_device::write_cb2)); @@ -629,9 +630,17 @@ void mac_state::macii(machine_config &config, bool cpu, asc_device::asc_type asc m_adbmodem->irq_callback().set(FUNC(mac_state::adb_irq_w)); m_via1->cb2_handler().set(m_adbmodem, FUNC(adbmodem_device::set_via_data)); config.set_perfect_quantum(m_maincpu); +#endif MACADB(config, m_macadb, C15M); +#if !MACII_USE_ADBMODEM + m_macadb->set_mcu_mode(false); + m_macadb->via_clock_callback().set(m_via1, FUNC(via6522_device::write_cb1)); + m_macadb->via_data_callback().set(m_via1, FUNC(via6522_device::write_cb2)); + m_macadb->adb_irq_callback().set(FUNC(mac_state::adb_irq_w)); +#else m_macadb->adb_data_callback().set(m_adbmodem, FUNC(adbmodem_device::set_adb_line)); +#endif RAM(config, m_ram); m_ram->set_default_size("2M"); @@ -776,6 +785,7 @@ void mac_state::macse30(machine_config &config) add_via1_adb(config, false); add_via2(config); +#if MACII_USE_ADBMODEM ADBMODEM(config, m_adbmodem, C7M); m_adbmodem->via_clock_callback().set(m_via1, FUNC(via6522_device::write_cb1)); m_adbmodem->via_data_callback().set(m_via1, FUNC(via6522_device::write_cb2)); @@ -783,9 +793,17 @@ void mac_state::macse30(machine_config &config) m_adbmodem->irq_callback().set(FUNC(mac_state::adb_irq_w)); m_via1->cb2_handler().set(m_adbmodem, FUNC(adbmodem_device::set_via_data)); config.set_perfect_quantum(m_maincpu); +#endif MACADB(config, m_macadb, C15M); +#if !MACII_USE_ADBMODEM + m_macadb->set_mcu_mode(false); + m_macadb->via_clock_callback().set(m_via1, FUNC(via6522_device::write_cb1)); + m_macadb->via_data_callback().set(m_via1, FUNC(via6522_device::write_cb2)); + m_macadb->adb_irq_callback().set(FUNC(mac_state::adb_irq_w)); +#else m_macadb->adb_data_callback().set(m_adbmodem, FUNC(adbmodem_device::set_adb_line)); +#endif RAM(config, m_ram); m_ram->set_default_size("2M"); diff --git a/src/mame/apple/mac.h b/src/mame/apple/mac.h index 587a0e64987..0c460f8f5a1 100644 --- a/src/mame/apple/mac.h +++ b/src/mame/apple/mac.h @@ -43,6 +43,8 @@ #define MAC_H_TOTAL (704) // (512+192) #define MAC_V_TOTAL (370) // (342+28) +#define MACII_USE_ADBMODEM (0) + // Mac driver data class mac_state:public driver_device diff --git a/src/mame/apple/mac_m.cpp b/src/mame/apple/mac_m.cpp index 53d9309584c..cf6ba0f5d08 100644 --- a/src/mame/apple/mac_m.cpp +++ b/src/mame/apple/mac_m.cpp @@ -492,6 +492,15 @@ WRITE_LINE_MEMBER(mac_state::mac_adb_via_out_cb2) { m_egret->set_via_data(state & 1); } +#if !MACII_USE_ADBMODEM + else + { + if (m_macadb) + { + m_macadb->adb_data_w(state); + } + } +#endif } /* ************************************************************************* @@ -570,6 +579,10 @@ uint8_t mac_state::mac_via_in_b() if (ADB_IS_BITBANG_CLASS) { + #if !MACII_USE_ADBMODEM + val |= m_macadb->get_adb_state() << 4; + #endif + if (!m_adb_irq_pending) { val |= 0x08; @@ -593,6 +606,10 @@ uint8_t mac_state::mac_via_in_b_ii() if (ADB_IS_BITBANG_CLASS) { +#if !MACII_USE_ADBMODEM + val |= m_macadb->get_adb_state() << 4; +#endif + if (!m_adb_irq_pending) { val |= 0x08; @@ -644,7 +661,11 @@ void mac_state::mac_via_out_b_bbadb(uint8_t data) } } +#if MACII_USE_ADBMODEM m_adbmodem->set_via_state((data & 0x30) >> 4); +#else + m_macadb->mac_adb_newaction((data & 0x30) >> 4); +#endif m_rtc->ce_w((data & 0x04)>>2); m_rtc->data_w(data & 0x01); diff --git a/src/mame/apple/macadb.cpp b/src/mame/apple/macadb.cpp index 76725041afa..9d6f919b0e9 100644 --- a/src/mame/apple/macadb.cpp +++ b/src/mame/apple/macadb.cpp @@ -202,8 +202,11 @@ macadb_device::macadb_device(const machine_config &mconfig, const char *tag, dev m_mouse1(*this, "MOUSE1"), m_mouse2(*this, "MOUSE2"), m_keys(*this, "KEY%u", 0), + write_via_clock(*this), + write_via_data(*this), write_adb_data(*this), - write_adb_irq(*this) + write_adb_irq(*this), + m_bIsMCUMode(true) { } @@ -214,6 +217,8 @@ ioport_constructor macadb_device::device_input_ports() const void macadb_device::device_start() { + write_via_clock.resolve_safe(); + write_via_data.resolve_safe(); write_adb_data.resolve_safe(); write_adb_irq.resolve_safe(); @@ -233,9 +238,13 @@ void macadb_device::device_start() save_item(NAME(m_adb_datasize)); save_item(NAME(m_adb_buffer)); save_item(NAME(m_adb_command)); + save_item(NAME(m_adb_send)); + save_item(NAME(m_adb_timer_ticks)); + save_item(NAME(m_adb_extclock)); save_item(NAME(m_adb_direction)); save_item(NAME(m_adb_listenreg)); save_item(NAME(m_adb_listenaddr)); + save_item(NAME(m_adb_last_talk)); save_item(NAME(m_adb_srq_switch)); save_item(NAME(m_adb_stream_ptr)); save_item(NAME(m_adb_linestate)); @@ -255,6 +264,22 @@ void macadb_device::device_start() save_item(NAME(m_adb_linein)); } +WRITE_LINE_MEMBER(macadb_device::adb_data_w) +{ + if (m_adb_timer_ticks > 0) + { + m_adb_command <<= 1; + if (state) + { + m_adb_command |= 1; + } + else + { + m_adb_command &= ~1; + } + } +} + /* ************************************************************************* * High-level ADB primitives used by all lower-level implementations * *************************************************************************/ @@ -487,12 +512,14 @@ void macadb_device::adb_talk() case ADB_CMD_RESET: LOGMASKED(LOG_TALK_LISTEN, "ADB RESET: reg %x address %x\n", reg, addr); m_adb_direction = 0; + m_adb_send = 0; break; case ADB_CMD_FLUSH: LOGMASKED(LOG_TALK_LISTEN, "ADB FLUSH: reg %x address %x\n", reg, addr); m_adb_direction = 0; + m_adb_send = 0; break; default: // reserved/unused @@ -522,6 +549,9 @@ void macadb_device::adb_talk() case 3: // talk LOGMASKED(LOG_TALK_LISTEN, "ADB TALK: reg %x address %x (K %x M %x)\n", reg, addr, m_adb_keybaddr, m_adb_mouseaddr); + // keep track of what device the Mac last TALKed to + m_adb_last_talk = addr; + m_adb_direction = 0; // output to Mac if (addr == m_adb_mouseaddr) { @@ -693,131 +723,290 @@ void macadb_device::adb_talk() TIMER_CALLBACK_MEMBER(macadb_device::mac_adb_tick) { - switch (m_adb_linestate) + if (m_bIsMCUMode) { - case LST_SRQNODATA: - set_adb_line(ASSERT_LINE); - m_adb_linestate = LST_IDLE; - break; - - case LST_TSTOPSTART: - LOGMASKED(LOG_LINESTATE, "Send: TStopStart begin\n"); - set_adb_line(ASSERT_LINE); - m_adb_timer->adjust(attotime::from_ticks(adb_short, adb_timebase)); - m_adb_linestate++; - break; - - case LST_TSTOPSTARTa: - LOGMASKED(LOG_LINESTATE, "Send: TStopStart end\n"); - set_adb_line(CLEAR_LINE); - m_adb_timer->adjust(attotime::from_ticks(adb_short, adb_timebase)); - m_adb_linestate++; - break; + switch (m_adb_linestate) + { + case LST_SRQNODATA: + set_adb_line(ASSERT_LINE); + m_adb_linestate = LST_IDLE; + break; - case LST_STARTBIT: - LOGMASKED(LOG_LINESTATE, "Send: Start bit\n"); - set_adb_line(ASSERT_LINE); - m_adb_timer->adjust(attotime::from_ticks(adb_long, adb_timebase)); - m_adb_linestate++; - break; + case LST_TSTOPSTART: + LOGMASKED(LOG_LINESTATE, "Send: TStopStart begin\n"); + set_adb_line(ASSERT_LINE); + m_adb_timer->adjust(attotime::from_ticks(adb_short, adb_timebase)); + m_adb_linestate++; + break; - case LST_SENDBIT0: - case LST_SENDBIT1: - case LST_SENDBIT2: - case LST_SENDBIT3: - case LST_SENDBIT4: - case LST_SENDBIT5: - case LST_SENDBIT6: - case LST_SENDBIT7: - set_adb_line(CLEAR_LINE); - if (m_adb_buffer[m_adb_stream_ptr] & 0x80) - { - LOGMASKED(LOG_LINESTATE, "Send: 1\n"); + case LST_TSTOPSTARTa: + LOGMASKED(LOG_LINESTATE, "Send: TStopStart end\n"); + set_adb_line(CLEAR_LINE); m_adb_timer->adjust(attotime::from_ticks(adb_short, adb_timebase)); - } - else - { - LOGMASKED(LOG_LINESTATE, "Send: 0\n"); + m_adb_linestate++; + break; + + case LST_STARTBIT: + LOGMASKED(LOG_LINESTATE, "Send: Start bit\n"); + set_adb_line(ASSERT_LINE); m_adb_timer->adjust(attotime::from_ticks(adb_long, adb_timebase)); - } - m_adb_linestate++; - break; + m_adb_linestate++; + break; - case LST_SENDBIT0a: - case LST_SENDBIT1a: - case LST_SENDBIT2a: - case LST_SENDBIT3a: - case LST_SENDBIT4a: - case LST_SENDBIT5a: - case LST_SENDBIT6a: - set_adb_line(ASSERT_LINE); - if (m_adb_buffer[m_adb_stream_ptr] & 0x80) + case LST_SENDBIT0: + case LST_SENDBIT1: + case LST_SENDBIT2: + case LST_SENDBIT3: + case LST_SENDBIT4: + case LST_SENDBIT5: + case LST_SENDBIT6: + case LST_SENDBIT7: + set_adb_line(CLEAR_LINE); + if (m_adb_buffer[m_adb_stream_ptr] & 0x80) + { + LOGMASKED(LOG_LINESTATE, "Send: 1\n"); + m_adb_timer->adjust(attotime::from_ticks(adb_short, adb_timebase)); + } + else + { + LOGMASKED(LOG_LINESTATE, "Send: 0\n"); + m_adb_timer->adjust(attotime::from_ticks(adb_long, adb_timebase)); + } + m_adb_linestate++; + break; + + case LST_SENDBIT0a: + case LST_SENDBIT1a: + case LST_SENDBIT2a: + case LST_SENDBIT3a: + case LST_SENDBIT4a: + case LST_SENDBIT5a: + case LST_SENDBIT6a: + set_adb_line(ASSERT_LINE); + if (m_adb_buffer[m_adb_stream_ptr] & 0x80) + { + m_adb_timer->adjust(attotime::from_ticks(adb_long, adb_timebase)); + } + else + { + m_adb_timer->adjust(attotime::from_ticks(adb_short, adb_timebase)); + } + m_adb_buffer[m_adb_stream_ptr] <<= 1; + m_adb_linestate++; + break; + + case LST_SENDBIT7a: + set_adb_line(ASSERT_LINE); + if (m_adb_buffer[m_adb_stream_ptr] & 0x80) + { +// printf(" "); + m_adb_timer->adjust(attotime::from_ticks(adb_long, adb_timebase)); + } + else + { +// printf(" "); + m_adb_timer->adjust(attotime::from_ticks(adb_short, adb_timebase)); + } + + m_adb_stream_ptr++; + if (m_adb_stream_ptr == m_adb_datasize) + { + m_adb_linestate++; + } + else + { + m_adb_linestate = LST_SENDBIT0; + } + break; + + case LST_SENDSTOP: + LOGMASKED(LOG_LINESTATE, "Send: Stop bit begin\n"); + set_adb_line(CLEAR_LINE); + m_adb_timer->adjust(attotime::from_ticks((adb_short*2), adb_timebase)); + m_adb_linestate++; + break; + + case LST_SENDSTOPa: + LOGMASKED(LOG_LINESTATE, "Send: Stop bit end\n"); + set_adb_line(ASSERT_LINE); + m_adb_timer->adjust(attotime::never); + m_adb_linestate = LST_IDLE; + break; + } + } + else + { + // for input to Mac, the VIA reads on the *other* clock edge, so update this here + if (!m_adb_direction) + { + write_via_data((m_adb_send & 0x80)>>7); + m_adb_send <<= 1; + } + + // do one clock transition on CB1 to advance the VIA shifter + //printf("ADB transition (%d)\n", m_adb_timer_ticks); + if (m_adb_direction) + { + write_via_clock(m_adb_extclock ^ 1); + write_via_clock(m_adb_extclock); + } + else + { + write_via_clock(m_adb_extclock); + write_via_clock(m_adb_extclock ^ 1); + } + + m_adb_timer_ticks--; + if (!m_adb_timer_ticks) + { + m_adb_timer->adjust(attotime::never); + + if ((m_adb_direction) && (!m_bIsMCUMode)) { - m_adb_timer->adjust(attotime::from_ticks(adb_long, adb_timebase)); + adb_talk(); + if((m_adb_last_talk == 2) && m_adb_datasize) { + m_adb_timer_ticks = 8; + m_adb_timer->adjust(attotime(0, ATTOSECONDS_IN_USEC(100))); + } } - else + + if (!(m_adb_direction) && !(m_bIsMCUMode)) { - m_adb_timer->adjust(attotime::from_ticks(adb_short, adb_timebase)); + // write_via_clock(m_adb_extclock); + write_via_clock(m_adb_extclock ^ 1); } - m_adb_buffer[m_adb_stream_ptr] <<= 1; - m_adb_linestate++; - break; + } + else + { + m_adb_timer->adjust(attotime(0, ATTOSECONDS_IN_USEC(200))); + } + } +} + +void macadb_device::mac_adb_newaction(int state) +{ + if (state != m_adb_state) + { + LOGMASKED(LOG_STATE, "New ADB state: %s\n", adb_statenames[state]); + + m_adb_state = state; + m_adb_timer_ticks = 8; + + switch (state) + { + case ADB_STATE_NEW_COMMAND: + m_adb_command = m_adb_send = 0; + m_adb_direction = 1; // Mac is shifting us a command + m_adb_waiting_cmd = 1; // we're going to get a command + write_adb_irq(CLEAR_LINE); + m_adb_timer->adjust(attotime(0, ATTOSECONDS_IN_USEC(100))); + break; + + case ADB_STATE_XFER_EVEN: + case ADB_STATE_XFER_ODD: + //printf("EVEN/ODD: adb datasize %d\n", m_adb_datasize); + if (m_adb_datasize > 0) + { + int i; + + // is something trying to send to the Mac? + if (m_adb_direction == 0) + { + // set up the byte + m_adb_send = m_adb_buffer[0]; + //printf("ADB sending %02x\n", m_adb_send); + m_adb_datasize--; + + // move down the rest of the buffer, if any + for (i = 0; i < m_adb_datasize; i++) + { + m_adb_buffer[i] = m_adb_buffer[i+1]; + } + } + + } + else + { + m_adb_send = 0; + write_adb_irq(ASSERT_LINE); + } + + m_adb_timer->adjust(attotime(0, ATTOSECONDS_IN_USEC(100))); + break; - case LST_SENDBIT7a: - set_adb_line(ASSERT_LINE); - if (m_adb_buffer[m_adb_stream_ptr] & 0x80) + case ADB_STATE_IDLE: + write_adb_irq(CLEAR_LINE); + break; + } + } +} + +void macadb_device::adb_vblank() +{ + if (m_adb_state == ADB_STATE_IDLE) + { + if (this->adb_pollmouse()) + { + // if the mouse was the last TALK, we can just send the new data + // otherwise we need to pull SRQ + if (m_adb_last_talk == m_adb_mouseaddr) { -// printf(" "); - m_adb_timer->adjust(attotime::from_ticks(adb_long, adb_timebase)); + // repeat last TALK to get updated data + m_adb_waiting_cmd = 1; + this->adb_talk(); + + m_adb_timer_ticks = 8; + this->m_adb_timer->adjust(attotime(0, ATTOSECONDS_IN_USEC(100))); } else { -// printf(" "); - m_adb_timer->adjust(attotime::from_ticks(adb_short, adb_timebase)); + write_adb_irq(ASSERT_LINE); + m_adb_command = m_adb_send = 0; + m_adb_timer_ticks = 1; // one tick should be sufficient to make it see the IRQ + this->m_adb_timer->adjust(attotime(0, ATTOSECONDS_IN_USEC(100))); + m_adb_srq_switch = 1; } - - m_adb_stream_ptr++; - if (m_adb_stream_ptr == m_adb_datasize) + } + else if (this->adb_pollkbd(0)) + { + if (m_adb_last_talk == m_adb_keybaddr) { - m_adb_linestate++; + // repeat last TALK to get updated data + m_adb_waiting_cmd = 1; + this->adb_talk(); + + m_adb_timer_ticks = 8; + this->m_adb_timer->adjust(attotime(0, ATTOSECONDS_IN_USEC(100))); } else { - m_adb_linestate = LST_SENDBIT0; + write_adb_irq(ASSERT_LINE); + m_adb_command = m_adb_send = 0; + m_adb_timer_ticks = 1; // one tick should be sufficient to make it see the IRQ + this->m_adb_timer->adjust(attotime(0, ATTOSECONDS_IN_USEC(100))); + m_adb_srq_switch = 1; } - break; - - case LST_SENDSTOP: - LOGMASKED(LOG_LINESTATE, "Send: Stop bit begin\n"); - set_adb_line(CLEAR_LINE); - m_adb_timer->adjust(attotime::from_ticks((adb_short*2), adb_timebase)); - m_adb_linestate++; - break; - - case LST_SENDSTOPa: - LOGMASKED(LOG_LINESTATE, "Send: Stop bit end\n"); - set_adb_line(ASSERT_LINE); - m_adb_timer->adjust(attotime::never); - m_adb_linestate = LST_IDLE; - break; + } } } -void macadb_device::adb_vblank() -{ -} - void macadb_device::device_reset() { int i; m_adb_srq_switch = 0; write_adb_irq(CLEAR_LINE); // no interrupt + m_adb_timer_ticks = 0; m_adb_command = 0; + m_adb_extclock = 0; + m_adb_send = 0; m_adb_waiting_cmd = 0; + m_adb_state = 0; m_adb_srqflag = false; + m_adb_state = ADB_STATE_NOTINIT; m_adb_direction = 0; m_adb_datasize = 0; + m_adb_last_talk = -1; m_adb_linestate = 0; diff --git a/src/mame/apple/macadb.h b/src/mame/apple/macadb.h index 2ea4b061dfe..0d11758b1ca 100644 --- a/src/mame/apple/macadb.h +++ b/src/mame/apple/macadb.h @@ -19,16 +19,23 @@ public: // construction/destruction macadb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + void set_mcu_mode(bool bMCUMode) { m_bIsMCUMode = bMCUMode; } + + auto via_clock_callback() { return write_via_clock.bind(); } + auto via_data_callback() { return write_via_data.bind(); } auto adb_data_callback() { return write_adb_data.bind(); } auto adb_irq_callback() { return write_adb_irq.bind(); } required_ioport m_mouse0, m_mouse1, m_mouse2; required_ioport_array<6> m_keys; - devcb_write_line write_adb_data, write_adb_irq; + devcb_write_line write_via_clock, write_via_data, write_adb_data, write_adb_irq; + DECLARE_WRITE_LINE_MEMBER(adb_data_w); DECLARE_WRITE_LINE_MEMBER(adb_linechange_w); void adb_vblank(); + void mac_adb_newaction(int state); + int32_t get_adb_state(void) { return m_adb_state; } protected: // device-level overrides @@ -37,6 +44,8 @@ protected: virtual void device_reset() override; private: + bool m_bIsMCUMode; + uint64_t m_last_adb_time; emu_timer *m_adb_timer; @@ -45,9 +54,9 @@ private: int m_key_matrix[7]; // ADB HLE state - int32_t m_adb_waiting_cmd, m_adb_datasize, m_adb_buffer[257]; - int32_t m_adb_command, m_adb_direction; - int32_t m_adb_listenreg, m_adb_listenaddr, m_adb_srq_switch; + int32_t m_adb_state, m_adb_waiting_cmd, m_adb_datasize, m_adb_buffer[257]; + int32_t m_adb_command, m_adb_send, m_adb_timer_ticks, m_adb_extclock, m_adb_direction; + int32_t m_adb_listenreg, m_adb_listenaddr, m_adb_last_talk, m_adb_srq_switch; int32_t m_adb_stream_ptr; int32_t m_adb_linestate; bool m_adb_srqflag; -- cgit v1.2.3