summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/coco/coco_multi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/coco/coco_multi.cpp')
-rw-r--r--src/devices/bus/coco/coco_multi.cpp222
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); }