diff options
Diffstat (limited to 'src/devices/bus/coco/coco_multi.cpp')
-rw-r--r-- | src/devices/bus/coco/coco_multi.cpp | 222 |
1 files changed, 153 insertions, 69 deletions
diff --git a/src/devices/bus/coco/coco_multi.cpp b/src/devices/bus/coco/coco_multi.cpp index 9b21a34f66f..18b75765b31 100644 --- a/src/devices/bus/coco/coco_multi.cpp +++ b/src/devices/bus/coco/coco_multi.cpp @@ -2,9 +2,9 @@ // copyright-holders:Nathan Woods /*************************************************************************** - coco_multi.c + coco_multi.cpp - Code for emulating CoCo's Multi-Pak Interface + Code for emulating CoCo's Multi-Pak Interface The Multi-Pak interface multiplexes all I/O lines from the Color Computer's expansion port to four identical ports. All I/O lines @@ -18,7 +18,7 @@ panel, four position switch. When adjusted the switch will direct the MPI to target these three I/O lines to the selected slot. - Second, the MPI will listen to writes to 0xff7f and respond accordingly: + Second, the MPI will listen to writes to $FF7F and respond accordingly: bit 0 --\___ Target *SCS to this slot number bit 1 --/ @@ -29,11 +29,11 @@ bit 6 ------ Ignore bit 7 ------ Ignore - After writing to 0xff7f, the position of the physical switch has no + After writing to $FF7F, the position of the physical switch has no effect until reset. - Reading is supported on 0xff7f. It will reflect the position of the - physical switch. Until data is written to 0xff7f, then it will only + Reading is supported on $FF7F. It will reflect the position of the + physical switch. Until data is written to $FF7F, then it will only reflect what has been written until a reset. A common modification users of the OS-9 operating system made was to @@ -46,8 +46,10 @@ Because of sloppy address decoding the original MPI also responds to $FF9F. No software is known to take advantage of this. After the introduction of the CoCo 3, which uses $FF9F internally, Tandy provided - free upgrades to any MPI to fix this problem. + free upgrades to any MPI to fix this problem. This behavior is not + emulated (yet). + Slots seem to be one-counted (i.e. - 1-4, not 0-3) by convention ***************************************************************************/ @@ -84,43 +86,27 @@ static SLOT_INTERFACE_START(coco_cart_slot4) SLOT_INTERFACE("pak", COCO_PAK) SLOT_INTERFACE_END -WRITE_LINE_MEMBER(coco_multipak_device::multi_cart_w) -{ - cococart_slot_device *cart = dynamic_cast<cococart_slot_device *>(owner()); - cart->m_cart_callback(state); -} - -WRITE_LINE_MEMBER(coco_multipak_device::multi_nmi_w) -{ - cococart_slot_device *cart = dynamic_cast<cococart_slot_device *>(owner()); - cart->m_nmi_callback(state); -} - -WRITE_LINE_MEMBER(coco_multipak_device::multi_halt_w) -{ - cococart_slot_device *cart = dynamic_cast<cococart_slot_device *>(owner()); - cart->m_halt_callback(state); -} static MACHINE_CONFIG_FRAGMENT(coco_multi) MCFG_COCO_CARTRIDGE_ADD(SLOT1_TAG, coco_cart_slot1_3, nullptr) - MCFG_COCO_CARTRIDGE_CART_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_cart_w)) - MCFG_COCO_CARTRIDGE_NMI_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_nmi_w)) - MCFG_COCO_CARTRIDGE_HALT_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_halt_w)) + MCFG_COCO_CARTRIDGE_CART_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_slot1_cart_w)) + MCFG_COCO_CARTRIDGE_NMI_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_slot1_nmi_w)) + MCFG_COCO_CARTRIDGE_HALT_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_slot1_halt_w)) MCFG_COCO_CARTRIDGE_ADD(SLOT2_TAG, coco_cart_slot1_3, nullptr) - MCFG_COCO_CARTRIDGE_CART_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_cart_w)) - MCFG_COCO_CARTRIDGE_NMI_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_nmi_w)) - MCFG_COCO_CARTRIDGE_HALT_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_halt_w)) + MCFG_COCO_CARTRIDGE_CART_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_slot2_cart_w)) + MCFG_COCO_CARTRIDGE_NMI_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_slot2_nmi_w)) + MCFG_COCO_CARTRIDGE_HALT_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_slot2_halt_w)) MCFG_COCO_CARTRIDGE_ADD(SLOT3_TAG, coco_cart_slot1_3, nullptr) - MCFG_COCO_CARTRIDGE_CART_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_cart_w)) - MCFG_COCO_CARTRIDGE_NMI_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_nmi_w)) - MCFG_COCO_CARTRIDGE_HALT_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_halt_w)) + MCFG_COCO_CARTRIDGE_CART_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_slot3_cart_w)) + MCFG_COCO_CARTRIDGE_NMI_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_slot3_nmi_w)) + MCFG_COCO_CARTRIDGE_HALT_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_slot3_halt_w)) MCFG_COCO_CARTRIDGE_ADD(SLOT4_TAG, coco_cart_slot4, "fdcv11") - MCFG_COCO_CARTRIDGE_CART_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_cart_w)) - MCFG_COCO_CARTRIDGE_NMI_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_nmi_w)) - MCFG_COCO_CARTRIDGE_HALT_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_halt_w)) + MCFG_COCO_CARTRIDGE_CART_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_slot4_cart_w)) + MCFG_COCO_CARTRIDGE_NMI_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_slot4_nmi_w)) + MCFG_COCO_CARTRIDGE_HALT_CB(DEVWRITELINE(DEVICE_SELF, coco_multipak_device, multi_slot4_halt_w)) MACHINE_CONFIG_END + //************************************************************************** // GLOBAL VARIABLES //************************************************************************** @@ -139,12 +125,11 @@ const device_type COCO_MULTIPAK = device_creator<coco_multipak_device>; coco_multipak_device::coco_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, COCO_MULTIPAK, "CoCo Multi-Pak Interface", tag, owner, clock, "coco_multipak", __FILE__), - device_cococart_interface( mconfig, *this ), m_owner(nullptr), m_select(0) - { + device_cococart_interface( mconfig, *this ), m_select(0) +{ } - //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- @@ -156,7 +141,6 @@ void coco_multipak_device::device_start() m_slots[1] = dynamic_cast<cococart_slot_device *>(subdevice(SLOT2_TAG)); m_slots[2] = dynamic_cast<cococart_slot_device *>(subdevice(SLOT3_TAG)); m_slots[3] = dynamic_cast<cococart_slot_device *>(subdevice(SLOT4_TAG)); - m_owner = dynamic_cast<cococart_slot_device *>(owner()); // install $FF7F handler write8_delegate wh = write8_delegate(FUNC(coco_multipak_device::ff7f_write), this); @@ -170,7 +154,6 @@ void coco_multipak_device::device_start() } - //------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- @@ -181,7 +164,6 @@ void coco_multipak_device::device_reset() } - //------------------------------------------------- // machine_config_additions - device-specific // machine configurations @@ -193,62 +175,72 @@ machine_config_constructor coco_multipak_device::device_mconfig_additions() cons } +//************************************************************************** +// INTERNAL ACCESSORS +//************************************************************************** + +cococart_slot_device &coco_multipak_device::owning_slot() +{ + return *dynamic_cast<cococart_slot_device *>(owner()); +} + //------------------------------------------------- -// get_cart_base +// active_scs_slot_number //------------------------------------------------- -uint8_t* coco_multipak_device::get_cart_base() +int coco_multipak_device::active_scs_slot_number() const { - return active_cts_slot()->get_cart_base(); + return ((m_select >> 0) & 0x03) + 1; } - //------------------------------------------------- -// read +// active_cts_slot_number //------------------------------------------------- -READ8_MEMBER(coco_multipak_device::read) +int coco_multipak_device::active_cts_slot_number() const { - return active_scs_slot()->read(space,offset); + return ((m_select >> 4) & 0x03) + 1; } - //------------------------------------------------- -// write +// slot //------------------------------------------------- -WRITE8_MEMBER(coco_multipak_device::write) +cococart_slot_device &coco_multipak_device::slot(int slot_number) { - active_scs_slot()->write(space,offset,data); + assert(slot_number >= 1 && slot_number <= 4); + return *m_slots[slot_number - 1]; } - //------------------------------------------------- -// set_sound_enable +// active_scs_slot //------------------------------------------------- -void coco_multipak_device::set_sound_enable(bool sound_enable) +cococart_slot_device &coco_multipak_device::active_scs_slot() { - for (cococart_slot_device *slot : m_slots) - slot->cart_set_line(cococart_slot_device::line::SOUND_ENABLE, sound_enable ? cococart_slot_device::line_value::ASSERT : cococart_slot_device::line_value::CLEAR); + int slot_number = active_scs_slot_number(); + return slot(slot_number); } - //------------------------------------------------- -// ff7f_write +// active_cts_slot //------------------------------------------------- -WRITE8_MEMBER(coco_multipak_device::ff7f_write) +cococart_slot_device &coco_multipak_device::active_cts_slot() { - set_select(data); + int slot_number = active_cts_slot_number(); + return slot(slot_number); } +//************************************************************************** +// METHODS +//************************************************************************** //------------------------------------------------- // set_select @@ -256,30 +248,122 @@ WRITE8_MEMBER(coco_multipak_device::ff7f_write) void coco_multipak_device::set_select(uint8_t new_select) { + // identify old value for CART, in case this needs to change + cococart_slot_device::line_value old_cart = active_cts_slot().get_line_value(cococart_slot_device::line::CART); + + // change value uint8_t xorval = m_select ^ new_select; m_select = new_select; - if (xorval & 0x30) + + // did the cartridge base change? + if (xorval & 0x03) cart_base_changed(); + + // did the CART line change? + cococart_slot_device::line_value new_cart = active_cts_slot().get_line_value(cococart_slot_device::line::CART); + if (new_cart != old_cart) + update_line(active_cts_slot_number(), cococart_slot_device::line::CART); +} + + +//------------------------------------------------- +// ff7f_write +//------------------------------------------------- + +WRITE8_MEMBER(coco_multipak_device::ff7f_write) +{ + set_select(data); } +//------------------------------------------------- +// update_line +//------------------------------------------------- + +void coco_multipak_device::update_line(int slot_number, cococart_slot_device::line line) +{ + bool propagate; + + // one of our child devices set a line; we may need to propagate it upwards + switch (line) + { + case cococart_slot_device::line::CART: + // only propagate if this is coming from the slot specified + propagate = slot_number == active_cts_slot_number(); + break; + + case cococart_slot_device::line::NMI: + case cococart_slot_device::line::HALT: + // always propagate these + propagate = true; + break; + + default: + // do nothing + propagate = false; + break; + } + + if (propagate) + owning_slot().set_line_value(line, slot(slot_number).get_line_value(line)); +} + //------------------------------------------------- -// active_scs_slot +// set_sound_enable //------------------------------------------------- -cococart_slot_device *coco_multipak_device::active_scs_slot(void) +void coco_multipak_device::set_sound_enable(bool sound_enable) { - return m_slots[(m_select >> 0) & 0x03]; + // the SOUND_ENABLE (SNDEN) line is different; it is controlled by the CPU + for (cococart_slot_device *slot : m_slots) + slot->set_line_value(cococart_slot_device::line::SOUND_ENABLE, sound_enable ? cococart_slot_device::line_value::ASSERT : cococart_slot_device::line_value::CLEAR); } +//------------------------------------------------- +// get_cart_base +//------------------------------------------------- + +uint8_t* coco_multipak_device::get_cart_base() +{ + return active_cts_slot().get_cart_base(); +} + //------------------------------------------------- -// active_cts_slot +// read +//------------------------------------------------- + +READ8_MEMBER(coco_multipak_device::read) +{ + return active_scs_slot().read(space, offset); +} + + +//------------------------------------------------- +// write //------------------------------------------------- -cococart_slot_device *coco_multipak_device::active_cts_slot(void) +WRITE8_MEMBER(coco_multipak_device::write) { - return m_slots[(m_select >> 4) & 0x03]; + active_scs_slot().write(space, offset, data); } + + +//------------------------------------------------- +// multiX_slotX_[cart|nmi|halt] trampolines +//------------------------------------------------- + +WRITE_LINE_MEMBER(coco_multipak_device::multi_slot1_cart_w) { update_line(1, cococart_slot_device::line::CART); } +WRITE_LINE_MEMBER(coco_multipak_device::multi_slot1_nmi_w) { update_line(1, cococart_slot_device::line::NMI); } +WRITE_LINE_MEMBER(coco_multipak_device::multi_slot1_halt_w) { update_line(1, cococart_slot_device::line::HALT); } +WRITE_LINE_MEMBER(coco_multipak_device::multi_slot2_cart_w) { update_line(2, cococart_slot_device::line::CART); } +WRITE_LINE_MEMBER(coco_multipak_device::multi_slot2_nmi_w) { update_line(2, cococart_slot_device::line::NMI); } +WRITE_LINE_MEMBER(coco_multipak_device::multi_slot2_halt_w) { update_line(2, cococart_slot_device::line::HALT); } +WRITE_LINE_MEMBER(coco_multipak_device::multi_slot3_cart_w) { update_line(3, cococart_slot_device::line::CART); } +WRITE_LINE_MEMBER(coco_multipak_device::multi_slot3_nmi_w) { update_line(3, cococart_slot_device::line::NMI); } +WRITE_LINE_MEMBER(coco_multipak_device::multi_slot3_halt_w) { update_line(3, cococart_slot_device::line::HALT); } +WRITE_LINE_MEMBER(coco_multipak_device::multi_slot4_cart_w) { update_line(4, cococart_slot_device::line::CART); } +WRITE_LINE_MEMBER(coco_multipak_device::multi_slot4_nmi_w) { update_line(4, cococart_slot_device::line::NMI); } +WRITE_LINE_MEMBER(coco_multipak_device::multi_slot4_halt_w) { update_line(4, cococart_slot_device::line::HALT); } |