summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus')
-rw-r--r--src/devices/bus/a2bus/a2bus.h1
-rw-r--r--src/devices/bus/a2bus/a2mockingboard.cpp107
-rw-r--r--src/devices/bus/a2bus/a2mockingboard.h51
-rw-r--r--src/devices/bus/a2bus/titan3plus2.cpp334
-rw-r--r--src/devices/bus/a2bus/titan3plus2.h64
-rw-r--r--src/devices/bus/adam/exp.h8
-rw-r--r--src/devices/bus/bw2/exp.h7
-rw-r--r--src/devices/bus/cbm2/exp.cpp9
-rw-r--r--src/devices/bus/cbm2/exp.h7
-rw-r--r--src/devices/bus/coco/coco_multi.cpp123
-rw-r--r--src/devices/bus/coco/coco_multi.h1
-rw-r--r--src/devices/bus/coco/coco_wpk.cpp201
-rw-r--r--src/devices/bus/coco/coco_wpk.h94
-rw-r--r--src/devices/bus/coco/coco_wpk2p.cpp56
-rw-r--r--src/devices/bus/coco/coco_wpk2p.h41
-rw-r--r--src/devices/bus/coco/cococart.cpp65
-rw-r--r--src/devices/bus/coco/cococart.h3
-rw-r--r--src/devices/bus/coco/dragon_claw.cpp212
-rw-r--r--src/devices/bus/coco/dragon_claw.h59
-rw-r--r--src/devices/bus/coco/dragon_msx2.cpp191
-rw-r--r--src/devices/bus/coco/dragon_msx2.h53
-rw-r--r--src/devices/bus/coco/dragon_serial.cpp154
-rw-r--r--src/devices/bus/coco/dragon_serial.h52
-rw-r--r--src/devices/bus/generic/slot.h2
-rw-r--r--src/devices/bus/isa/isa_cards.cpp2
-rw-r--r--src/devices/bus/isa/lrk330.cpp130
-rw-r--r--src/devices/bus/isa/lrk330.h38
-rw-r--r--src/devices/bus/mc10/mc10_cart.cpp230
-rw-r--r--src/devices/bus/mc10/mc10_cart.h118
-rw-r--r--src/devices/bus/mc10/mcx128.cpp371
-rw-r--r--src/devices/bus/mc10/mcx128.h15
-rw-r--r--src/devices/bus/mc10/pak.cpp69
-rw-r--r--src/devices/bus/mc10/pak.h37
-rw-r--r--src/devices/bus/mc10/ram.cpp78
-rw-r--r--src/devices/bus/mc10/ram.h14
-rw-r--r--src/devices/bus/nes/act53.cpp66
-rw-r--r--src/devices/bus/nes/act53.h11
-rw-r--r--src/devices/bus/nes/nes_slot.h4
-rw-r--r--src/devices/bus/newbrain/eim.cpp2
-rw-r--r--src/devices/bus/newbrain/exp.h7
-rw-r--r--src/devices/bus/newbrain/fdc.cpp14
-rw-r--r--src/devices/bus/newbrain/fdc.h5
-rw-r--r--src/devices/bus/odyssey2/rom.cpp2
-rw-r--r--src/devices/bus/pet/exp.h7
-rw-r--r--src/devices/bus/plus4/c1551.cpp4
-rw-r--r--src/devices/bus/plus4/exp.cpp9
-rw-r--r--src/devices/bus/plus4/exp.h7
-rw-r--r--src/devices/bus/pofo/exp.h7
-rw-r--r--src/devices/bus/pofo/hpc104.cpp4
-rw-r--r--src/devices/bus/saitek_osa/expansion.cpp16
-rw-r--r--src/devices/bus/saitek_osa/expansion.h6
-rw-r--r--src/devices/bus/saitek_osa/modules.cpp22
-rw-r--r--src/devices/bus/saitek_osa/modules.h16
-rw-r--r--src/devices/bus/vic10/exp.cpp9
-rw-r--r--src/devices/bus/vic10/exp.h8
-rw-r--r--src/devices/bus/vic20/exp.h8
-rw-r--r--src/devices/bus/vip/exp.h7
-rw-r--r--src/devices/bus/vme/vme.cpp54
-rw-r--r--src/devices/bus/vme/vme.h30
-rw-r--r--src/devices/bus/vme/vme_fccpu20.cpp2
-rw-r--r--src/devices/bus/vme/vme_fcisio.cpp1
-rw-r--r--src/devices/bus/vme/vme_fcscsi.cpp1
-rw-r--r--src/devices/bus/vme/vme_hcpu30.cpp2
-rw-r--r--src/devices/bus/vme/vme_mvme350.cpp1
-rw-r--r--src/devices/bus/vme/vme_mzr8300.cpp1
65 files changed, 2974 insertions, 356 deletions
diff --git a/src/devices/bus/a2bus/a2bus.h b/src/devices/bus/a2bus/a2bus.h
index 1c7d94bbcdc..5a10f06de39 100644
--- a/src/devices/bus/a2bus/a2bus.h
+++ b/src/devices/bus/a2bus/a2bus.h
@@ -149,6 +149,7 @@ public:
virtual void write_inh_rom(uint16_t offset, uint8_t data) { }
virtual uint16_t inh_start() { return INH_START_INVALID; }
virtual uint16_t inh_end() { return INH_END_INVALID; }
+ virtual bool inh_check(uint16_t offset, bool bIsWrite) { return false; }
virtual int inh_type() { return INH_NONE; }
device_a2bus_card_interface *next() const { return m_next; }
diff --git a/src/devices/bus/a2bus/a2mockingboard.cpp b/src/devices/bus/a2bus/a2mockingboard.cpp
index 6073e843371..380e9988a8b 100644
--- a/src/devices/bus/a2bus/a2mockingboard.cpp
+++ b/src/devices/bus/a2bus/a2mockingboard.cpp
@@ -41,11 +41,13 @@ DEFINE_DEVICE_TYPE(A2BUS_ECHOPLUS, a2bus_echoplus_device, "a2echop", "S
void a2bus_ayboard_device::add_common_devices(machine_config &config)
{
MOS6522(config, m_via1, 1022727);
+ m_via1->readpa_handler().set(FUNC(a2bus_ayboard_device::via1_in_a));
m_via1->writepa_handler().set(FUNC(a2bus_ayboard_device::via1_out_a));
m_via1->writepb_handler().set(FUNC(a2bus_ayboard_device::via1_out_b));
m_via1->irq_handler().set(FUNC(a2bus_ayboard_device::via1_irq_w));
MOS6522(config, m_via2, 1022727);
+ m_via2->readpa_handler().set(FUNC(a2bus_ayboard_device::via2_in_a));
m_via2->writepa_handler().set(FUNC(a2bus_ayboard_device::via2_out_a));
m_via2->writepb_handler().set(FUNC(a2bus_ayboard_device::via2_out_b));
m_via2->irq_handler().set(FUNC(a2bus_ayboard_device::via2_irq_w));
@@ -101,6 +103,9 @@ void a2bus_echoplus_device::device_add_mconfig(machine_config &config)
{
add_common_devices(config);
+ config.device_remove(VIA2_TAG);
+ m_via1->writepb_handler().set(FUNC(a2bus_ayboard_device::via1_out_b));
+
AY8913(config, m_ay2, 1022727);
m_ay2->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
@@ -165,7 +170,7 @@ void a2bus_ayboard_device::device_reset()
read_cnxx - called for reads from this card's cnxx space
-------------------------------------------------*/
-uint8_t a2bus_ayboard_device::read_cnxx(uint8_t offset)
+u8 a2bus_ayboard_device::read_cnxx(u8 offset)
{
if (offset <= 0x7f)
{
@@ -179,9 +184,15 @@ uint8_t a2bus_ayboard_device::read_cnxx(uint8_t offset)
return 0;
}
-uint8_t a2bus_phasor_device::read_cnxx(uint8_t offset)
+u8 a2bus_echoplus_device::read_cnxx(u8 offset)
{
- uint8_t ret = 0;
+ m_last_cnxx_addr = offset;
+ return m_via1->read(offset & 0xf);
+}
+
+u8 a2bus_phasor_device::read_cnxx(u8 offset)
+{
+ u8 ret = 0;
int via_sel;
if (m_native)
@@ -212,7 +223,7 @@ uint8_t a2bus_phasor_device::read_cnxx(uint8_t offset)
write_cnxx - called for writes to this card's c0nx space
-------------------------------------------------*/
-void a2bus_ayboard_device::write_cnxx(uint8_t offset, uint8_t data)
+void a2bus_ayboard_device::write_cnxx(u8 offset, u8 data)
{
// When the SSI-263 is emulated, Cn40 will write to both the VIA and
// the first SSI-263, and Cn20 will write to both the VIA and the
@@ -227,7 +238,13 @@ void a2bus_ayboard_device::write_cnxx(uint8_t offset, uint8_t data)
}
}
-void a2bus_phasor_device::write_cnxx(uint8_t offset, uint8_t data)
+void a2bus_echoplus_device::write_cnxx(u8 offset, u8 data)
+{
+ m_last_cnxx_addr = offset;
+ m_via1->write(offset & 0xf, data);
+}
+
+void a2bus_phasor_device::write_cnxx(u8 offset, u8 data)
{
if ((offset < 0x20) || (offset >= 0x80 && offset < 0xa0))
{
@@ -277,12 +294,12 @@ WRITE_LINE_MEMBER( a2bus_ayboard_device::via2_irq_w )
}
}
-void a2bus_ayboard_device::via1_out_a(uint8_t data)
+void a2bus_ayboard_device::via1_out_a(u8 data)
{
m_porta1 = data;
}
-void a2bus_ayboard_device::via1_out_b(uint8_t data)
+void a2bus_ayboard_device::via1_out_b(u8 data)
{
if (!BIT(data, 2))
{
@@ -310,7 +327,65 @@ void a2bus_ayboard_device::via1_out_b(uint8_t data)
}
}
-void a2bus_phasor_device::via1_out_b(uint8_t data)
+void a2bus_echoplus_device::via1_out_b(u8 data)
+{
+ if (!(m_last_cnxx_addr & 0x80))
+ {
+ if (!BIT(data, 2))
+ {
+ m_ay1->reset_w();
+ }
+ else
+ {
+ switch (data & 3)
+ {
+ case 0: // BDIR=0, BC1=0 (inactive)
+ break;
+
+ case 1: // BDIR=0, BC1=1 (read PSG)
+ m_porta1 = m_ay1->data_r();
+ break;
+
+ case 2: // BDIR=1, BC1=0 (write PSG)
+ m_ay1->data_w(m_porta1);
+ break;
+
+ case 3: // BDIR=1, BC1=1 (latch)
+ m_ay1->address_w(m_porta1);
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (!BIT(data, 2))
+ {
+ m_ay2->reset_w();
+ }
+ else
+ {
+ switch (data & 3)
+ {
+ case 0: // BDIR=0, BC1=0 (inactive)
+ break;
+
+ case 1: // BDIR=0, BC1=1 (read PSG)
+ m_porta1 = m_ay2->data_r();
+ break;
+
+ case 2: // BDIR=1, BC1=0 (write PSG)
+ m_ay2->data_w(m_porta1);
+ break;
+
+ case 3: // BDIR=1, BC1=1 (latch)
+ m_ay2->address_w(m_porta1);
+ break;
+ }
+ }
+ }
+}
+
+void a2bus_phasor_device::via1_out_b(u8 data)
{
if (!(data & 4))
{
@@ -359,12 +434,12 @@ void a2bus_phasor_device::via1_out_b(uint8_t data)
}
}
-void a2bus_ayboard_device::via2_out_a(uint8_t data)
+void a2bus_ayboard_device::via2_out_a(u8 data)
{
m_porta2 = data;
}
-void a2bus_ayboard_device::via2_out_b(uint8_t data)
+void a2bus_ayboard_device::via2_out_b(u8 data)
{
if (!BIT(data, 2))
{
@@ -392,7 +467,7 @@ void a2bus_ayboard_device::via2_out_b(uint8_t data)
}
}
-void a2bus_phasor_device::via2_out_b(uint8_t data)
+void a2bus_phasor_device::via2_out_b(u8 data)
{
if (!BIT(data, 2))
{
@@ -463,20 +538,20 @@ void a2bus_phasor_device::set_clocks()
}
}
-uint8_t a2bus_phasor_device::read_c0nx(uint8_t offset)
+u8 a2bus_phasor_device::read_c0nx(u8 offset)
{
m_native = BIT(offset, 0);
set_clocks();
return 0xff;
}
-void a2bus_phasor_device::write_c0nx(uint8_t offset, uint8_t data)
+void a2bus_phasor_device::write_c0nx(u8 offset, u8 data)
{
m_native = BIT(offset, 0);
set_clocks();
}
-uint8_t a2bus_echoplus_device::read_c0nx(uint8_t offset)
+u8 a2bus_echoplus_device::read_c0nx(u8 offset)
{
switch (offset)
{
@@ -487,7 +562,7 @@ uint8_t a2bus_echoplus_device::read_c0nx(uint8_t offset)
return 0;
}
-void a2bus_echoplus_device::write_c0nx(uint8_t offset, uint8_t data)
+void a2bus_echoplus_device::write_c0nx(u8 offset, u8 data)
{
switch (offset)
{
@@ -513,7 +588,7 @@ WRITE_LINE_MEMBER( a2bus_mockingboard_device::write_via1_cb2 )
m_last_cb2_state = state;
}
-void a2bus_mockingboard_device::via1_out_b(uint8_t data)
+void a2bus_mockingboard_device::via1_out_b(u8 data)
{
m_portb1 = data;
diff --git a/src/devices/bus/a2bus/a2mockingboard.h b/src/devices/bus/a2bus/a2mockingboard.h
index 44acff10006..539363c1f10 100644
--- a/src/devices/bus/a2bus/a2mockingboard.h
+++ b/src/devices/bus/a2bus/a2mockingboard.h
@@ -28,10 +28,12 @@ class a2bus_ayboard_device:
public:
DECLARE_WRITE_LINE_MEMBER( via1_irq_w );
DECLARE_WRITE_LINE_MEMBER( via2_irq_w );
- void via1_out_a(uint8_t data);
- virtual void via1_out_b(uint8_t data);
- void via2_out_a(uint8_t data);
- virtual void via2_out_b(uint8_t data);
+ u8 via1_in_a() { return m_porta1; }
+ u8 via2_in_a() { return m_porta2; }
+ void via1_out_a(u8 data);
+ virtual void via1_out_b(u8 data);
+ void via2_out_a(u8 data);
+ virtual void via2_out_b(u8 data);
protected:
// construction/destruction
@@ -42,20 +44,20 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
// overrides of standard a2bus slot functions
- virtual uint8_t read_c0nx(uint8_t offset) override { return 0xff; }
- virtual void write_c0nx(uint8_t offset, uint8_t data) override { }
- virtual uint8_t read_cnxx(uint8_t offset) override;
- virtual void write_cnxx(uint8_t offset, uint8_t data) override;
+ virtual u8 read_c0nx(u8 offset) override { return 0xff; }
+ virtual void write_c0nx(u8 offset, u8 data) override { }
+ virtual u8 read_cnxx(u8 offset) override;
+ virtual void write_cnxx(u8 offset, u8 data) override;
void add_common_devices(machine_config &config);
required_device<via6522_device> m_via1;
- required_device<via6522_device> m_via2;
+ optional_device<via6522_device> m_via2;
required_device<ay8913_device> m_ay1;
required_device<ay8913_device> m_ay2;
- uint8_t m_porta1;
- uint8_t m_porta2;
+ u8 m_porta1;
+ u8 m_porta2;
};
class a2bus_mockingboard_device : public a2bus_ayboard_device
@@ -63,7 +65,7 @@ class a2bus_mockingboard_device : public a2bus_ayboard_device
public:
a2bus_mockingboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual void via1_out_b(uint8_t data) override;
+ virtual void via1_out_b(u8 data) override;
protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_reset() override;
@@ -73,7 +75,7 @@ protected:
private:
DECLARE_WRITE_LINE_MEMBER(write_via1_cb2);
- uint8_t m_portb1;
+ u8 m_portb1;
int m_last_cb2_state;
};
@@ -82,16 +84,16 @@ class a2bus_phasor_device : public a2bus_ayboard_device
public:
a2bus_phasor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void via1_out_b(uint8_t data) override;
- void via2_out_b(uint8_t data) override;
+ void via1_out_b(u8 data) override;
+ void via2_out_b(u8 data) override;
protected:
virtual void device_add_mconfig(machine_config &config) override;
- virtual uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
- virtual uint8_t read_cnxx(uint8_t offset) override;
- virtual void write_cnxx(uint8_t offset, uint8_t data) override;
+ virtual u8 read_c0nx(u8 offset) override;
+ virtual void write_c0nx(u8 offset, u8 data) override;
+ virtual u8 read_cnxx(u8 offset) override;
+ virtual void write_cnxx(u8 offset, u8 data) override;
required_device<ay8913_device> m_ay3;
required_device<ay8913_device> m_ay4;
@@ -110,10 +112,17 @@ public:
protected:
virtual void device_add_mconfig(machine_config &config) override;
- virtual uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
+ virtual void via1_out_b(u8 data) override;
+
+ virtual u8 read_c0nx(u8 offset) override;
+ virtual void write_c0nx(u8 offset, u8 data) override;
+ virtual u8 read_cnxx(u8 offset) override;
+ virtual void write_cnxx(u8 offset, u8 data) override;
required_device<tms5220_device> m_tms;
+
+private:
+ u8 m_last_cnxx_addr;
};
// device type definition
diff --git a/src/devices/bus/a2bus/titan3plus2.cpp b/src/devices/bus/a2bus/titan3plus2.cpp
new file mode 100644
index 00000000000..e04dc03448a
--- /dev/null
+++ b/src/devices/bus/a2bus/titan3plus2.cpp
@@ -0,0 +1,334 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ titan3plus3.cpp
+
+ Implemention of the Titan "/// Plus //"" card.
+ By R. Belmont, based on reverse-engineering by Rob Justice.
+
+ This extends the Apple ///'s II emulation to include a 128K
+ extended language card and Apple II compatible game I/O.
+
+ The card enables itself if the /// is at 1 MHz and accesses the
+ card's $CNxx ROM space. If the /// goes back to 2 MHz mode at
+ any time, the card disables itself.
+
+ Address ranges this messes with:
+ $C05X - passed through to ///, but also used for annunciators on A2 gameio
+ $C06X - /// doesn't see when card enabled, A2 paddles
+ $C07X - passed through to ///, but also used for A2 paddle reset
+ $C08X - unused by /// (language card control)
+ $D000-$FFFF: usual (for A2) language card space. Not so usual for ///.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "titan3plus2.h"
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(A2BUS_TITAN3PLUS2, a2bus_titan3plus2_device, "titan3p2", "Titan /// Plus //")
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+void a2bus_titan3plus2_device::device_add_mconfig(machine_config &config)
+{
+ APPLE2_GAMEIO(config, m_gameio, apple2_gameio_device::default_options, nullptr);
+}
+
+a2bus_titan3plus2_device::a2bus_titan3plus2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock), device_a2bus_card_interface(mconfig, *this),
+ m_gameio(*this, "gameio"),
+ m_inh_state(0), m_last_offset(0), m_dxxx_bank(0), m_main_bank(0), m_enabled(false)
+{
+}
+
+a2bus_titan3plus2_device::a2bus_titan3plus2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_titan3plus2_device(mconfig, A2BUS_TITAN3PLUS2, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_titan3plus2_device::device_start()
+{
+ memset(m_ram, 0, 128*1024);
+
+ save_item(NAME(m_inh_state));
+ save_item(NAME(m_ram));
+ save_item(NAME(m_dxxx_bank));
+ save_item(NAME(m_main_bank));
+ save_item(NAME(m_last_offset));
+ save_item(NAME(m_enabled));
+
+ m_x_calibration = m_y_calibration = attotime::from_nsec(10800).as_double();
+}
+
+void a2bus_titan3plus2_device::device_reset()
+{
+ m_inh_state = INH_NONE;
+ m_dxxx_bank = 0;
+ m_main_bank = 0;
+ m_last_offset = -1;
+}
+
+void a2bus_titan3plus2_device::do_io(int offset)
+{
+ int old_inh_state = m_inh_state;
+
+ switch (offset)
+ {
+ case 0x1: case 0x3: case 0x9: case 0xb:
+ if (offset != m_last_offset)
+ {
+ m_last_offset = offset;
+ return;
+ }
+ break;
+ }
+ m_last_offset = offset;
+
+ if (offset & 4)
+ {
+ switch (offset)
+ {
+ case 0x4: m_main_bank = 0x00000; break;
+ case 0x5: m_main_bank = 0x04000; break;
+ case 0x6: m_main_bank = 0x08000; break;
+ case 0x7: m_main_bank = 0x0c000; break;
+ case 0xc: m_main_bank = 0x10000; break;
+ case 0xd: m_main_bank = 0x14000; break;
+ case 0xe: m_main_bank = 0x18000; break;
+ case 0xf: m_main_bank = 0x1c000; break;
+ }
+ }
+ else
+ {
+ m_inh_state = INH_NONE;
+ m_dxxx_bank = 0;
+
+ if (offset & 0x1)
+ {
+ m_inh_state |= INH_WRITE;
+ }
+
+ switch(offset & 0x03)
+ {
+ case 0x00:
+ case 0x03:
+ m_inh_state |= INH_READ;
+ break;
+ }
+
+ if (!(offset & 8))
+ {
+ m_dxxx_bank = 0x1000;
+ }
+ }
+
+ if (m_inh_state != old_inh_state)
+ {
+ recalc_slot_inh();
+ }
+
+ #if 0
+ printf("LC: (ofs %x) new state %c%c dxxx=%04x main=%05x\n",
+ offset,
+ (m_inh_state & INH_READ) ? 'R' : 'x',
+ (m_inh_state & INH_WRITE) ? 'W' : 'x',
+ m_dxxx_bank, m_main_bank);
+ #endif
+}
+
+
+/*-------------------------------------------------
+ read_c08x - called for reads from the LC switches
+-------------------------------------------------*/
+
+uint8_t a2bus_titan3plus2_device::read_c08x(uint8_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ do_io(offset & 0xf);
+ }
+ return 0xff;
+}
+
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to the LC switches
+-------------------------------------------------*/
+
+void a2bus_titan3plus2_device::write_c08x(uint8_t offset, uint8_t data)
+{
+ do_io(offset & 0xf);
+}
+
+uint8_t a2bus_titan3plus2_device::read_inh_rom(uint16_t offset)
+{
+ if (offset < 0xd000)
+ {
+ if ((offset >= 0xc080) && (offset <= 0xc08f))
+ {
+ return read_c08x(offset & 0xf);
+ }
+
+ if ((offset >= 0xc060) && (offset <= 0xc06f))
+ {
+ switch (offset & 0x7)
+ {
+ case 1: // button 0
+ return (m_gameio->sw0_r() ? 0x80 : 0);
+
+ case 2: // button 1
+ return (m_gameio->sw1_r() ? 0x80 : 0);
+
+ case 3: // button 2
+ return (m_gameio->sw2_r() ? 0x80 : 0);
+
+ case 4: // joy 1 X axis
+ if (!m_gameio->is_device_connected())
+ return 0x80;
+ return ((machine().time().as_double() < m_joystick_x1_time) ? 0x80 : 0);
+
+ case 5: // joy 1 Y axis
+ if (!m_gameio->is_device_connected())
+ return 0x80;
+ return ((machine().time().as_double() < m_joystick_y1_time) ? 0x80 : 0);
+
+ case 6: // joy 2 X axis
+ if (!m_gameio->is_device_connected())
+ return 0x80;
+ return ((machine().time().as_double() < m_joystick_x2_time) ? 0x80 : 0);
+
+ case 7: // joy 2 Y axis
+ if (!m_gameio->is_device_connected())
+ return 0x80;
+ return ((machine().time().as_double() < m_joystick_y2_time) ? 0x80 : 0);
+ }
+ }
+ }
+ else
+ {
+ if (offset < 0xe000)
+ {
+ return m_ram[(offset & 0xfff) + m_dxxx_bank + m_main_bank];
+ }
+
+ return m_ram[(offset & 0x1fff) + 0x2000 + m_main_bank];
+ }
+
+ return 0xff;
+}
+
+void a2bus_titan3plus2_device::write_inh_rom(uint16_t offset, uint8_t data)
+{
+ if (offset < 0xd000)
+ {
+ if ((offset >= 0xc080) && (offset <= 0xc08f))
+ {
+ write_c08x(offset & 0xf, data);
+ return;
+ }
+ }
+ else
+ {
+ if (offset < 0xe000)
+ {
+ m_ram[(offset & 0xfff) + m_dxxx_bank + m_main_bank] = data;
+ return;
+ }
+
+ m_ram[(offset & 0x1fff) + 0x2000 + m_main_bank] = data;
+ }
+}
+
+u8 a2bus_titan3plus2_device::read_cnxx(u8 offset)
+{
+ m_enabled = true;
+ return 0xff;
+}
+
+// returns if we want to /INH a read or write to a specific address
+bool a2bus_titan3plus2_device::inh_check(u16 offset, bool bIsWrite)
+{
+ if (!m_enabled)
+ {
+ return false;
+ }
+
+ // handle LC
+ if (offset >= 0xd000)
+ {
+ if ((bIsWrite) && (m_inh_state & INH_WRITE))
+ {
+ return true;
+ }
+
+ if (!(bIsWrite) && (m_inh_state & INH_READ))
+ {
+ return true;
+ }
+ }
+
+ if ((offset >= 0xc080) && (offset <= 0xc08f))
+ {
+ return true;
+ }
+
+ if ((offset >= 0xc070) && (offset <= 0xc07f))
+ {
+ m_joystick_x1_time = machine().time().as_double() + m_x_calibration * m_gameio->pdl0_r();
+ m_joystick_y1_time = machine().time().as_double() + m_y_calibration * m_gameio->pdl1_r();
+ m_joystick_x2_time = machine().time().as_double() + m_x_calibration * m_gameio->pdl2_r();
+ m_joystick_y2_time = machine().time().as_double() + m_y_calibration * m_gameio->pdl3_r();
+
+ return false; // Apple /// should still handle this
+ }
+
+ if ((offset >= 0xc060) && (offset <= 0xc06f))
+ {
+ return true;
+ }
+
+ if ((offset >= 0xc058) && (offset <= 0xc05f))
+ {
+ switch (offset & 0xf)
+ {
+ case 8:
+ case 9:
+ m_gameio->an0_w(offset & 1);
+ break;
+ case 0xa:
+ case 0xb:
+ m_gameio->an1_w(offset & 1);
+ break;
+ case 0xc:
+ case 0xd:
+ m_gameio->an2_w(offset & 1);
+ break;
+ case 0xe:
+ case 0xf:
+ m_gameio->an3_w(offset & 1);
+ break;
+ }
+ return false; // Apple /// should still see this
+ }
+
+ return false;
+}
diff --git a/src/devices/bus/a2bus/titan3plus2.h b/src/devices/bus/a2bus/titan3plus2.h
new file mode 100644
index 00000000000..f162f115d8e
--- /dev/null
+++ b/src/devices/bus/a2bus/titan3plus2.h
@@ -0,0 +1,64 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ titan3plus2.h
+
+ Implemention of the Titan /// Plus II card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_TITAN3PLUS2_H
+#define MAME_BUS_A2BUS_TITAN3PLUS2_H
+
+#pragma once
+
+#include "a2bus.h"
+#include "bus/a2gameio/gameio.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_titan3plus2_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_titan3plus2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_titan3plus2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ // overrides of standard a2bus slot functions
+ virtual u8 read_inh_rom(u16 offset) override;
+ virtual void write_inh_rom(u16 offset, u8 data) override;
+ virtual bool inh_check(uint16_t offset, bool bIsWrite) override;
+
+private:
+ required_device<apple2_gameio_device> m_gameio;
+
+ u8 read_c08x(u8 offset);
+ void write_c08x(u8 offset, u8 data);
+ u8 read_cnxx(u8 offset) override;
+ void do_io(int offset);
+
+ int m_inh_state;
+ int m_last_offset;
+ int m_dxxx_bank;
+ int m_main_bank;
+ u8 m_ram[128*1024];
+ bool m_enabled;
+
+ double m_joystick_x1_time, m_joystick_y1_time, m_joystick_x2_time, m_joystick_y2_time, m_x_calibration, m_y_calibration;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_TITAN3PLUS2, a2bus_titan3plus2_device)
+
+#endif // MAME_BUS_A2BUS_TITAN3PLUS2_H
diff --git a/src/devices/bus/adam/exp.h b/src/devices/bus/adam/exp.h
index ee74bf0396a..d9e993c3a1f 100644
--- a/src/devices/bus/adam/exp.h
+++ b/src/devices/bus/adam/exp.h
@@ -15,14 +15,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define ADAM_LEFT_EXPANSION_SLOT_TAG "slot1"
-#define ADAM_CENTER_EXPANSION_SLOT_TAG "slot2"
-#define ADAM_RIGHT_EXPANSION_SLOT_TAG "slot3"
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/bw2/exp.h b/src/devices/bus/bw2/exp.h
index dfb5924351b..6c6acf11f9a 100644
--- a/src/devices/bus/bw2/exp.h
+++ b/src/devices/bus/bw2/exp.h
@@ -43,13 +43,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define BW2_EXPANSION_SLOT_TAG "exp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/cbm2/exp.cpp b/src/devices/bus/cbm2/exp.cpp
index a824ecd051e..cc0f3516bc5 100644
--- a/src/devices/bus/cbm2/exp.cpp
+++ b/src/devices/bus/cbm2/exp.cpp
@@ -76,15 +76,6 @@ cbm2_expansion_slot_device::cbm2_expansion_slot_device(const machine_config &mco
void cbm2_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // inherit bus clock
- // FIXME: this should be unnecessary as slots pass DERIVED_CLOCK(1, 1) through by default
- if (clock() == 0)
- {
- cbm2_expansion_slot_device *root = machine().root_device().subdevice<cbm2_expansion_slot_device>(CBM2_EXPANSION_SLOT_TAG);
- assert(root);
- set_unscaled_clock(root->clock());
- }
}
diff --git a/src/devices/bus/cbm2/exp.h b/src/devices/bus/cbm2/exp.h
index 9781e4ac05a..b9f967137ca 100644
--- a/src/devices/bus/cbm2/exp.h
+++ b/src/devices/bus/cbm2/exp.h
@@ -34,13 +34,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define CBM2_EXPANSION_SLOT_TAG "exp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/coco/coco_multi.cpp b/src/devices/bus/coco/coco_multi.cpp
index 7006281286f..2061c905b3f 100644
--- a/src/devices/bus/coco/coco_multi.cpp
+++ b/src/devices/bus/coco/coco_multi.cpp
@@ -101,6 +101,8 @@ namespace
INPUT_CHANGED_MEMBER( switch_changed );
protected:
+ coco_multipak_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
@@ -119,10 +121,12 @@ namespace
virtual address_space &cartridge_space() override;
virtual ioport_constructor device_input_ports() const override;
- private:
// device references
required_device_array<cococart_slot_device, 4> m_slots;
+ void update_line(int slot_number, line ln);
+
+ private:
// internal state
u8 m_select;
u8 m_block;
@@ -138,24 +142,24 @@ namespace
void set_select(u8 new_select);
u8 ff7f_read();
void ff7f_write(u8 data);
- void update_line(int slot_number, line ln);
-
- DECLARE_WRITE_LINE_MEMBER(multi_slot1_cart_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot1_nmi_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot1_halt_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot2_cart_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot2_nmi_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot2_halt_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot3_cart_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot3_nmi_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot3_halt_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot4_cart_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot4_nmi_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot4_halt_w);
};
};
+// ======================> dragon_multipak_device
+
+class dragon_multipak_device : public coco_multipak_device
+{
+public:
+ // construction/destruction
+ dragon_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
@@ -175,21 +179,54 @@ static void coco_cart_slot4(device_slot_interface &device)
void coco_multipak_device::device_add_mconfig(machine_config &config)
{
COCOCART_SLOT(config, m_slots[0], DERIVED_CLOCK(1, 1), coco_cart_slot1_3, nullptr);
- m_slots[0]->cart_callback().set(FUNC(coco_multipak_device::multi_slot1_cart_w));
- m_slots[0]->nmi_callback().set(FUNC(coco_multipak_device::multi_slot1_nmi_w));
- m_slots[0]->halt_callback().set(FUNC(coco_multipak_device::multi_slot1_halt_w));
+ m_slots[0]->cart_callback().set([this](int state) { update_line(1, line::CART); });
+ m_slots[0]->nmi_callback().set([this](int state) { update_line(1, line::NMI); });
+ m_slots[0]->halt_callback().set([this](int state) { update_line(1, line::HALT); });
COCOCART_SLOT(config, m_slots[1], DERIVED_CLOCK(1, 1), coco_cart_slot1_3, nullptr);
- m_slots[1]->cart_callback().set(FUNC(coco_multipak_device::multi_slot2_cart_w));
- m_slots[1]->nmi_callback().set(FUNC(coco_multipak_device::multi_slot2_nmi_w));
- m_slots[1]->halt_callback().set(FUNC(coco_multipak_device::multi_slot2_halt_w));
+ m_slots[1]->cart_callback().set([this](int state) { update_line(2, line::CART); });
+ m_slots[1]->nmi_callback().set([this](int state) { update_line(2, line::NMI); });
+ m_slots[1]->halt_callback().set([this](int state) { update_line(2, line::HALT); });
COCOCART_SLOT(config, m_slots[2], DERIVED_CLOCK(1, 1), coco_cart_slot1_3, nullptr);
- m_slots[2]->cart_callback().set(FUNC(coco_multipak_device::multi_slot3_cart_w));
- m_slots[2]->nmi_callback().set(FUNC(coco_multipak_device::multi_slot3_nmi_w));
- m_slots[2]->halt_callback().set(FUNC(coco_multipak_device::multi_slot3_halt_w));
+ m_slots[2]->cart_callback().set([this](int state) { update_line(3, line::CART); });
+ m_slots[2]->nmi_callback().set([this](int state) { update_line(3, line::NMI); });
+ m_slots[2]->halt_callback().set([this](int state) { update_line(3, line::HALT); });
COCOCART_SLOT(config, m_slots[3], DERIVED_CLOCK(1, 1), coco_cart_slot4, "fdcv11");
- m_slots[3]->cart_callback().set(FUNC(coco_multipak_device::multi_slot4_cart_w));
- m_slots[3]->nmi_callback().set(FUNC(coco_multipak_device::multi_slot4_nmi_w));
- m_slots[3]->halt_callback().set(FUNC(coco_multipak_device::multi_slot4_halt_w));
+ m_slots[3]->cart_callback().set([this](int state) { update_line(4, line::CART); });
+ m_slots[3]->nmi_callback().set([this](int state) { update_line(4, line::NMI); });
+ m_slots[3]->halt_callback().set([this](int state) { update_line(4, line::HALT); });
+}
+
+
+static void dragon_cart_slot1_3(device_slot_interface &device)
+{
+ dragon_cart_add_basic_devices(device);
+}
+
+static void dragon_cart_slot4(device_slot_interface &device)
+{
+ dragon_cart_add_basic_devices(device);
+ dragon_cart_add_fdcs(device);
+}
+
+
+void dragon_multipak_device::device_add_mconfig(machine_config &config)
+{
+ COCOCART_SLOT(config, m_slots[0], DERIVED_CLOCK(1, 1), dragon_cart_slot1_3, nullptr);
+ m_slots[0]->cart_callback().set([this](int state) { update_line(1, line::CART); });
+ m_slots[0]->nmi_callback().set([this](int state) { update_line(1, line::NMI); });
+ m_slots[0]->halt_callback().set([this](int state) { update_line(1, line::HALT); });
+ COCOCART_SLOT(config, m_slots[1], DERIVED_CLOCK(1, 1), dragon_cart_slot1_3, nullptr);
+ m_slots[1]->cart_callback().set([this](int state) { update_line(2, line::CART); });
+ m_slots[1]->nmi_callback().set([this](int state) { update_line(2, line::NMI); });
+ m_slots[1]->halt_callback().set([this](int state) { update_line(2, line::HALT); });
+ COCOCART_SLOT(config, m_slots[2], DERIVED_CLOCK(1, 1), dragon_cart_slot1_3, nullptr);
+ m_slots[2]->cart_callback().set([this](int state) { update_line(3, line::CART); });
+ m_slots[2]->nmi_callback().set([this](int state) { update_line(3, line::NMI); });
+ m_slots[2]->halt_callback().set([this](int state) { update_line(3, line::HALT); });
+ COCOCART_SLOT(config, m_slots[3], DERIVED_CLOCK(1, 1), dragon_cart_slot4, "dragon_fdc");
+ m_slots[3]->cart_callback().set([this](int state) { update_line(4, line::CART); });
+ m_slots[3]->nmi_callback().set([this](int state) { update_line(4, line::NMI); });
+ m_slots[3]->halt_callback().set([this](int state) { update_line(4, line::HALT); });
}
INPUT_PORTS_START( coco_multipack )
@@ -206,6 +243,7 @@ INPUT_PORTS_END
//**************************************************************************
DEFINE_DEVICE_TYPE_PRIVATE(COCO_MULTIPAK, device_cococart_interface, coco_multipak_device, "coco_multipack", "CoCo Multi-Pak Interface")
+DEFINE_DEVICE_TYPE_PRIVATE(DRAGON_MULTIPAK, device_cococart_interface, dragon_multipak_device, "dragon_multipack", "Dragon Multi-Pak Interface")
@@ -226,13 +264,22 @@ ioport_constructor coco_multipak_device::device_input_ports() const
// coco_multipak_device - constructor
//-------------------------------------------------
-coco_multipak_device::coco_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : device_t(mconfig, COCO_MULTIPAK, tag, owner, clock)
+coco_multipak_device::coco_multipak_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
, device_cococart_interface(mconfig, *this)
, m_slots(*this, "slot%u", 1), m_select(0), m_block(0)
{
}
+coco_multipak_device::coco_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : coco_multipak_device(mconfig, COCO_MULTIPAK, tag, owner, clock)
+{
+}
+
+dragon_multipak_device::dragon_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : coco_multipak_device(mconfig, DRAGON_MULTIPAK, tag, owner, clock)
+{
+}
//-------------------------------------------------
// device_start - device-specific startup
@@ -486,24 +533,6 @@ void coco_multipak_device::scs_write(offs_t offset, u8 data)
//-------------------------------------------------
-// multiX_slotX_[cart|nmi|halt] trampolines
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot1_cart_w) { update_line(1, line::CART); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot1_nmi_w) { update_line(1, line::NMI); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot1_halt_w) { update_line(1, line::HALT); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot2_cart_w) { update_line(2, line::CART); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot2_nmi_w) { update_line(2, line::NMI); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot2_halt_w) { update_line(2, line::HALT); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot3_cart_w) { update_line(3, line::CART); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot3_nmi_w) { update_line(3, line::NMI); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot3_halt_w) { update_line(3, line::HALT); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot4_cart_w) { update_line(4, line::CART); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot4_nmi_w) { update_line(4, line::NMI); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot4_halt_w) { update_line(4, line::HALT); }
-
-
-//-------------------------------------------------
// cartridge_space
//-------------------------------------------------
diff --git a/src/devices/bus/coco/coco_multi.h b/src/devices/bus/coco/coco_multi.h
index eb66aee9660..94e9c6bbc05 100644
--- a/src/devices/bus/coco/coco_multi.h
+++ b/src/devices/bus/coco/coco_multi.h
@@ -9,5 +9,6 @@
// device type definition
DECLARE_DEVICE_TYPE(COCO_MULTIPAK, device_cococart_interface)
+DECLARE_DEVICE_TYPE(DRAGON_MULTIPAK, device_cococart_interface)
#endif // MAME_BUS_COCO_COCO_MULTIPAK_H
diff --git a/src/devices/bus/coco/coco_wpk.cpp b/src/devices/bus/coco/coco_wpk.cpp
new file mode 100644
index 00000000000..8841c2960ea
--- /dev/null
+++ b/src/devices/bus/coco/coco_wpk.cpp
@@ -0,0 +1,201 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ PBJ Word-Pak/Word-Pak II - 80 Column Video Cartridge
+
+ TODO:
+ - the R6545 Transparent Mode used to update video RAM needs some attention.
+ - original PBJ WorkPak (not II or RS) had an optional Basic Driver ROM (undumped).
+ - does WordPak II use different character ROM?
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_wpk.h"
+#include "render.h"
+#include "screen.h"
+
+
+//-------------------------------------------------
+// ROM( coco_wpk )
+//-------------------------------------------------
+
+ROM_START(coco_wpk)
+ ROM_REGION(0x0800, "chargen", 0)
+ ROM_LOAD("chr_gen_4.0.rom", 0x0000, 0x0800, CRC(6e9a671a) SHA1(0ff5fae512c7f1abe138504d51492404dd86be03)) // from PBJ WordPak RS
+ROM_END
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(COCO_WPK, coco_wpk_device, "coco_wpk", "CoCo WordPak")
+DEFINE_DEVICE_TYPE(COCO_WPK2, coco_wpk2_device, "coco_wpk2", "CoCo WordPak II")
+DEFINE_DEVICE_TYPE(COCO_WPKRS, coco_wpkrs_device, "coco_wpkrs", "CoCo WordPak RS")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// coco_wpk_device - constructor
+//-------------------------------------------------
+
+coco_wpk_device::coco_wpk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this )
+ , m_crtc(*this, "crtc")
+ , m_palette(*this, "palette")
+ , m_chargen(*this, "chargen")
+ , m_video_addr(0)
+ , m_video_data(0)
+{
+}
+
+coco_wpk_device::coco_wpk_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : coco_wpk_device(mconfig, COCO_WPK, tag, owner, clock)
+{
+}
+
+coco_wpk2_device::coco_wpk2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : coco_wpk_device(mconfig, COCO_WPK2, tag, owner, clock)
+{
+}
+
+coco_wpkrs_device::coco_wpkrs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : coco_wpk_device(mconfig, COCO_WPKRS, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_wpk_device::device_start()
+{
+ m_video_ram = std::make_unique<u8[]>(0x800);
+
+ save_pointer(NAME(m_video_ram), 0x800);
+ save_item(NAME(m_video_addr));
+}
+
+void coco_wpk2_device::device_start()
+{
+ coco_wpk_device::device_start();
+}
+
+void coco_wpkrs_device::device_start()
+{
+ coco_wpk_device::device_start();
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void coco_wpk_device::device_reset()
+{
+ install_readwrite_handler(0xff98, 0xff98, read8smo_delegate(*m_crtc, FUNC(r6545_1_device::status_r)), write8smo_delegate(*m_crtc, FUNC(r6545_1_device::address_w)));
+ install_readwrite_handler(0xff99, 0xff99, read8smo_delegate(*m_crtc, FUNC(r6545_1_device::register_r)), write8smo_delegate(*m_crtc, FUNC(r6545_1_device::register_w)));
+ install_write_handler(0xff9b, 0xff9b, write8smo_delegate(*this, FUNC(coco_wpkrs_device::crtc_display_w)));
+}
+
+void coco_wpk2_device::device_reset()
+{
+ coco_wpk_device::device_reset();
+
+ install_write_handler(0xff9c, 0xff9c, write8smo_delegate(*this, FUNC(coco_wpk2_device::video_select_w)));
+
+ machine().render().first_target()->set_view(0);
+}
+
+void coco_wpkrs_device::device_reset()
+{
+ install_readwrite_handler(0xff76, 0xff76, read8smo_delegate(*m_crtc, FUNC(r6545_1_device::status_r)), write8smo_delegate(*m_crtc, FUNC(r6545_1_device::address_w)));
+ install_readwrite_handler(0xff77, 0xff77, read8smo_delegate(*m_crtc, FUNC(r6545_1_device::register_r)), write8smo_delegate(*m_crtc, FUNC(r6545_1_device::register_w)));
+ install_write_handler(0xff79, 0xff79, write8smo_delegate(*this, FUNC(coco_wpkrs_device::crtc_display_w)));
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void coco_wpk_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(14.318181_MHz_XTAL, 896, 0, 640, 290, 0, 240);
+ screen.set_screen_update("crtc", FUNC(mc6845_device::screen_update));
+
+ PALETTE(config, m_palette, palette_device::MONOCHROME);
+
+ R6545_1(config, m_crtc, 14.318181_MHz_XTAL / 8);
+ m_crtc->set_screen("screen");
+ m_crtc->set_show_border_area(false);
+ m_crtc->set_char_width(8);
+ m_crtc->set_on_update_addr_change_callback(FUNC(coco_wpkrs_device::crtc_addr));
+ m_crtc->set_update_row_callback(FUNC(coco_wpkrs_device::crtc_update_row));
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *coco_wpk_device::device_rom_region() const
+{
+ return ROM_NAME( coco_wpk );
+}
+
+
+void coco_wpk_device::crtc_display_w(u8 data)
+{
+ //logerror("crtc_display_w: %02x\n", data);
+ m_video_ram[m_video_addr] = data;
+
+ m_crtc->register_r();
+}
+
+
+MC6845_ON_UPDATE_ADDR_CHANGED(coco_wpk_device::crtc_addr)
+{
+ //logerror("crtc_addr: %04x %d\n", address, strobe);
+ m_video_addr = address;
+}
+
+
+MC6845_UPDATE_ROW(coco_wpk_device::crtc_update_row)
+{
+ u32 *p = &bitmap.pix(y);
+
+ for (int column = 0; column < x_count; column++)
+ {
+ u8 code = m_video_ram[(ma + column) & 0x7ff];
+ u16 addr = (code << 4) | (ra & 0x0f);
+ u8 data = m_chargen->base()[addr & 0x7ff];
+
+ if (column == cursor_x)
+ {
+ data = 0xff;
+ }
+
+ for (int bit = 0; bit < 8; bit++)
+ {
+ *p++ = m_palette->pen(BIT(data, 0) && de);
+
+ data >>= 1;
+ }
+ }
+}
+
+
+void coco_wpk2_device::video_select_w(u8 data)
+{
+ // software video switch (Word-Pak II only)
+ machine().render().first_target()->set_view(BIT(data, 6));
+}
diff --git a/src/devices/bus/coco/coco_wpk.h b/src/devices/bus/coco/coco_wpk.h
new file mode 100644
index 00000000000..65534dd3709
--- /dev/null
+++ b/src/devices/bus/coco/coco_wpk.h
@@ -0,0 +1,94 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_COCO_COCO_WPK_H
+#define MAME_BUS_COCO_COCO_WPK_H
+
+#pragma once
+
+#include "cococart.h"
+#include "video/mc6845.h"
+#include "emupal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> coco_wpk_device
+
+class coco_wpk_device :
+ public device_t,
+ public device_cococart_interface
+{
+public:
+ static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
+
+ // construction/destruction
+ coco_wpk_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // construction/destruction
+ coco_wpk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ required_device<r6545_1_device> m_crtc;
+ required_device<palette_device> m_palette;
+ required_memory_region m_chargen;
+
+ u16 m_video_addr;
+ u8 m_video_data;
+
+ std::unique_ptr<u8[]> m_video_ram;
+
+ void crtc_display_w(u8 data);
+ MC6845_ON_UPDATE_ADDR_CHANGED(crtc_addr);
+ MC6845_UPDATE_ROW(crtc_update_row);
+};
+
+
+// ======================> coco_wpk2_device
+
+class coco_wpk2_device : public coco_wpk_device
+{
+public:
+ // construction/destruction
+ coco_wpk2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ void video_select_w(u8 data);
+};
+
+
+// ======================> coco_wpkrs_device
+
+class coco_wpkrs_device : public coco_wpk_device
+{
+public:
+ // construction/destruction
+ coco_wpkrs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(COCO_WPK, coco_wpk_device)
+DECLARE_DEVICE_TYPE(COCO_WPK2, coco_wpk2_device)
+DECLARE_DEVICE_TYPE(COCO_WPKRS, coco_wpkrs_device)
+
+#endif // MAME_BUS_COCO_COCO_WPK_H
diff --git a/src/devices/bus/coco/coco_wpk2p.cpp b/src/devices/bus/coco/coco_wpk2p.cpp
new file mode 100644
index 00000000000..62fb2504bf7
--- /dev/null
+++ b/src/devices/bus/coco/coco_wpk2p.cpp
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ CoCo WordPak 2+
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_wpk2p.h"
+#include "screen.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(COCO_WPK2P, coco_wpk2p_device, "coco_wpk2p", "CoCo WordPak 2+")
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// coco_wpk2p_device - constructor
+//-------------------------------------------------
+
+coco_wpk2p_device::coco_wpk2p_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, COCO_WPK2P, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this )
+ , m_v9958(*this, "v9958")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_wpk2p_device::device_start()
+{
+ install_readwrite_handler(0xff78, 0xff7b, read8sm_delegate(*m_v9958, FUNC(v9958_device::read)), write8sm_delegate(*m_v9958, FUNC(v9958_device::write)));
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void coco_wpk2p_device::device_add_mconfig(machine_config &config)
+{
+ /* video hardware */
+ V9958(config, m_v9958, 21.477272_MHz_XTAL);
+ m_v9958->set_screen_ntsc("screen");
+ m_v9958->set_vram_size(0x20000);
+ m_v9958->int_cb().set([this](int state) { set_line_value(line::NMI, state); });
+ SCREEN(config, "screen", SCREEN_TYPE_RASTER);
+}
diff --git a/src/devices/bus/coco/coco_wpk2p.h b/src/devices/bus/coco/coco_wpk2p.h
new file mode 100644
index 00000000000..f6c3debc766
--- /dev/null
+++ b/src/devices/bus/coco/coco_wpk2p.h
@@ -0,0 +1,41 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_COCO_COCO_WPK2P_H
+#define MAME_BUS_COCO_COCO_WPK2P_H
+
+#pragma once
+
+#include "cococart.h"
+#include "video/v9938.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> coco_wpk2p_device
+
+class coco_wpk2p_device :
+ public device_t,
+ public device_cococart_interface
+{
+public:
+ // construction/destruction
+ coco_wpk2p_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<v9958_device> m_v9958;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(COCO_WPK2P, coco_wpk2p_device)
+
+#endif // MAME_BUS_COCO_COCO_WPK2P_H
diff --git a/src/devices/bus/coco/cococart.cpp b/src/devices/bus/coco/cococart.cpp
index 8f733cd6c6a..28e97457114 100644
--- a/src/devices/bus/coco/cococart.cpp
+++ b/src/devices/bus/coco/cococart.cpp
@@ -54,6 +54,17 @@
#include "coco_ssc.h"
#include "coco_stecomp.h"
#include "coco_sym12.h"
+#include "coco_wpk.h"
+#include "coco_wpk2p.h"
+
+#include "dragon_amtor.h"
+#include "dragon_claw.h"
+#include "dragon_fdc.h"
+#include "dragon_jcbsnd.h"
+#include "dragon_jcbspch.h"
+#include "dragon_msx2.h"
+#include "dragon_serial.h"
+#include "dragon_sprites.h"
/***************************************************************************
@@ -702,12 +713,17 @@ void coco_cart_add_basic_devices(device_slot_interface &device)
device.option_add("gmc", COCO_PAK_GMC);
device.option_add("max", COCO_PAK_MAX);
device.option_add("midi", COCO_MIDI);
+ device.option_add("msx2", DRAGON_MSX2);
device.option_add("orch90", COCO_ORCH90);
device.option_add("ram", COCO_PAK_RAM);
device.option_add("rs232", COCO_RS232);
device.option_add("ssc", COCO_SSC);
device.option_add("stecomp", COCO_STEREO_COMPOSER);
device.option_add("sym12", COCO_SYM12);
+ device.option_add("wpk", COCO_WPK);
+ device.option_add("wpk2", COCO_WPK2);
+ device.option_add("wpkrs", COCO_WPKRS);
+ device.option_add("wpk2p", COCO_WPK2P);
}
@@ -737,3 +753,52 @@ void coco_cart_add_multi_pak(device_slot_interface &device)
// and the Multi-Pak itself is optional because they cannot be daisy chained
device.option_add("multi", COCO_MULTIPAK);
}
+
+
+//-------------------------------------------------
+// dragon_cart_add_basic_devices
+//-------------------------------------------------
+
+void dragon_cart_add_basic_devices(device_slot_interface &device)
+{
+ device.option_add_internal("amtor", DRAGON_AMTOR);
+ device.option_add("ccpsg", COCO_PSG);
+ device.option_add("claw", DRAGON_CLAW);
+ device.option_add("gmc", COCO_PAK_GMC);
+ device.option_add("jcbsnd", DRAGON_JCBSND);
+ device.option_add("jcbspch", DRAGON_JCBSPCH);
+ device.option_add("max", COCO_PAK_MAX);
+ device.option_add("midi", DRAGON_MIDI);
+ device.option_add("msx2", DRAGON_MSX2);
+ device.option_add("orch90", COCO_ORCH90);
+ device.option_add("pak", COCO_PAK);
+ device.option_add("serial", DRAGON_SERIAL);
+ device.option_add("ram", COCO_PAK_RAM);
+ device.option_add("sprites", DRAGON_SPRITES);
+ device.option_add("ssc", COCO_SSC);
+ device.option_add("stecomp", COCO_STEREO_COMPOSER);
+ device.option_add("sym12", COCO_SYM12);
+ device.option_add("wpk2p", COCO_WPK2P);
+}
+
+
+//-------------------------------------------------
+// dragon_cart_add_fdcs
+//-------------------------------------------------
+
+void dragon_cart_add_fdcs(device_slot_interface &device)
+{
+ device.option_add("dragon_fdc", DRAGON_FDC);
+ device.option_add("premier_fdc", PREMIER_FDC);
+ device.option_add("sdtandy_fdc", SDTANDY_FDC);
+}
+
+
+//-------------------------------------------------
+// dragon_cart_add_multi_pak
+//-------------------------------------------------
+
+void dragon_cart_add_multi_pak(device_slot_interface &device)
+{
+ device.option_add("multi", DRAGON_MULTIPAK);
+}
diff --git a/src/devices/bus/coco/cococart.h b/src/devices/bus/coco/cococart.h
index 78176588969..d2e33085956 100644
--- a/src/devices/bus/coco/cococart.h
+++ b/src/devices/bus/coco/cococart.h
@@ -231,5 +231,8 @@ private:
void coco_cart_add_basic_devices(device_slot_interface &device);
void coco_cart_add_fdcs(device_slot_interface &device);
void coco_cart_add_multi_pak(device_slot_interface &device);
+void dragon_cart_add_basic_devices(device_slot_interface &device);
+void dragon_cart_add_fdcs(device_slot_interface &device);
+void dragon_cart_add_multi_pak(device_slot_interface &device);
#endif // MAME_BUS_COCO_COCOCART_H
diff --git a/src/devices/bus/coco/dragon_claw.cpp b/src/devices/bus/coco/dragon_claw.cpp
new file mode 100644
index 00000000000..a4c00b0f71a
--- /dev/null
+++ b/src/devices/bus/coco/dragon_claw.cpp
@@ -0,0 +1,212 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ The Dragon's Claw from Lucidata
+
+ http://archive.worldofdragon.org/index.php?title=The_Dragon%27s_Claw
+
+ The Dragon's Claw is an extension cartridge for the Dragon by Lucidata.
+ It features two parallel I/O ports. One with the BBC User Port pinout,
+ and the second with a Centronics Printer Port pinout.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "dragon_claw.h"
+#include "bus/bbc/userport/userport.h"
+#include "bus/centronics/ctronics.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(DRAGON_CLAW, device_cococart_interface, dragon_claw_device, "dragon_claw", "The Dragon's Claw")
+
+//-------------------------------------------------
+// INPUT_PORTS( claw )
+//-------------------------------------------------
+
+INPUT_PORTS_START(claw)
+ PORT_START("LINKS")
+ PORT_CONFNAME(0x03, 0x00, "L1 Address Selection")
+ PORT_CONFSETTING(0x00, "$FF80")
+ PORT_CONFSETTING(0x01, "$FF90")
+ PORT_CONFSETTING(0x02, "$FFA0")
+ PORT_CONFSETTING(0x03, "$FFB0")
+ PORT_CONFNAME(0x04, 0x00, "L2 Interrupt Line")
+ PORT_CONFSETTING(0x00, "NMI")
+ PORT_CONFSETTING(0x04, "CART")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor dragon_claw_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(claw);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// dragon_claw_device - constructor
+//-------------------------------------------------
+
+dragon_claw_device::dragon_claw_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, DRAGON_CLAW, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this )
+ , m_via(*this, "via")
+ , m_slot(*this, "slot")
+ , m_links(*this, "LINKS")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void dragon_claw_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void dragon_claw_device::device_reset()
+{
+ uint8_t addr = (m_links->read() & 0x03) << 8;
+
+ install_readwrite_handler(0xff80 | addr, 0xff8f | addr, read8sm_delegate(*m_via, FUNC(via6522_device::read)), write8sm_delegate(*m_via, FUNC(via6522_device::write)));
+}
+
+static void dragon_cart(device_slot_interface &device)
+{
+ dragon_cart_add_basic_devices(device);
+ dragon_cart_add_fdcs(device);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void dragon_claw_device::device_add_mconfig(machine_config &config)
+{
+ MOS6522(config, m_via, DERIVED_CLOCK(1, 1));
+ m_via->writepa_handler().set("cent_data_out", FUNC(output_latch_device::write));
+ m_via->readpb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_r));
+ m_via->writepb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_w));
+ m_via->ca2_handler().set("centronics", FUNC(centronics_device::write_strobe));
+ m_via->cb1_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb1));
+ m_via->cb2_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb2));
+ m_via->irq_handler().set(FUNC(dragon_claw_device::irq_w)); // link L2 selects either NMI or CART line
+
+ bbc_userport_slot_device &userport(BBC_USERPORT_SLOT(config, "userport", bbc_userport_devices, nullptr));
+ userport.cb1_handler().set(m_via, FUNC(via6522_device::write_cb1));
+ userport.cb2_handler().set(m_via, FUNC(via6522_device::write_cb2));
+
+ centronics_device &centronics(CENTRONICS(config, "centronics", centronics_devices, nullptr));
+ centronics.ack_handler().set(m_via, FUNC(via6522_device::write_ca1));
+ output_latch_device &latch(OUTPUT_LATCH(config, "cent_data_out"));
+ centronics.set_output_latch(latch);
+
+ COCOCART_SLOT(config, m_slot, DERIVED_CLOCK(1, 1), dragon_cart, nullptr);
+ m_slot->cart_callback().set([this](int state) { set_line_value(line::CART, state); });
+ m_slot->nmi_callback().set([this](int state) { set_line_value(line::NMI, state); });
+ m_slot->halt_callback().set([this](int state) { set_line_value(line::HALT, state); });
+}
+
+WRITE_LINE_MEMBER(dragon_claw_device::irq_w)
+{
+ if (m_links->read() & 0x04)
+ set_line_value(line::CART, state);
+ else
+ set_line_value(line::NMI, state);
+}
+
+
+//-------------------------------------------------
+// set_sound_enable
+//-------------------------------------------------
+
+void dragon_claw_device::set_sound_enable(bool sound_enable)
+{
+ m_slot->set_line_value(line::SOUND_ENABLE, sound_enable ? line_value::ASSERT : line_value::CLEAR);
+}
+
+
+//-------------------------------------------------
+// get_cart_base
+//-------------------------------------------------
+
+u8 *dragon_claw_device::get_cart_base()
+{
+ return m_slot->get_cart_base();
+}
+
+
+//-------------------------------------------------
+// get_cart_size
+//-------------------------------------------------
+
+u32 dragon_claw_device::get_cart_size()
+{
+ return m_slot->get_cart_size();
+}
+
+
+//-------------------------------------------------
+// cts_read
+//-------------------------------------------------
+
+u8 dragon_claw_device::cts_read(offs_t offset)
+{
+ return m_slot->cts_read(offset);
+}
+
+
+//-------------------------------------------------
+// cts_write
+//-------------------------------------------------
+
+void dragon_claw_device::cts_write(offs_t offset, u8 data)
+{
+ m_slot->cts_write(offset, data);
+}
+
+
+//-------------------------------------------------
+// scs_read
+//-------------------------------------------------
+
+u8 dragon_claw_device::scs_read(offs_t offset)
+{
+ return m_slot->scs_read(offset);
+}
+
+
+//-------------------------------------------------
+// scs_write
+//-------------------------------------------------
+
+void dragon_claw_device::scs_write(offs_t offset, u8 data)
+{
+ m_slot->scs_write(offset, data);
+}
+
+
+//-------------------------------------------------
+// cartridge_space
+//-------------------------------------------------
+
+address_space &dragon_claw_device::cartridge_space()
+{
+ return device_cococart_interface::cartridge_space();
+}
diff --git a/src/devices/bus/coco/dragon_claw.h b/src/devices/bus/coco/dragon_claw.h
new file mode 100644
index 00000000000..9743b5b0b3c
--- /dev/null
+++ b/src/devices/bus/coco/dragon_claw.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_COCO_DRAGON_CLAW_H
+#define MAME_BUS_COCO_DRAGON_CLAW_H
+
+#pragma once
+
+#include "cococart.h"
+#include "machine/6522via.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> dragon_claw_device
+
+class dragon_claw_device :
+ public device_t,
+ public device_cococart_interface,
+ public device_cococart_host_interface
+{
+public:
+ // construction/destruction
+ dragon_claw_device(const machine_config& mconfig, const char* tag, device_t* owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config& config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual u8 cts_read(offs_t offset) override;
+ virtual void cts_write(offs_t offset, u8 data) override;
+ virtual u8 scs_read(offs_t offset) override;
+ virtual void scs_write(offs_t offset, u8 data) override;
+ virtual void set_sound_enable(bool sound_enable) override;
+
+ virtual u8 *get_cart_base() override;
+ virtual u32 get_cart_size() override;
+
+ virtual address_space &cartridge_space() override;
+
+private:
+ DECLARE_WRITE_LINE_MEMBER(irq_w);
+
+ required_device<via6522_device> m_via;
+ required_device<cococart_slot_device> m_slot;
+ required_ioport m_links;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(DRAGON_CLAW, device_cococart_interface)
+
+#endif // MAME_BUS_COCO_DRAGON_CLAW_H
diff --git a/src/devices/bus/coco/dragon_msx2.cpp b/src/devices/bus/coco/dragon_msx2.cpp
new file mode 100644
index 00000000000..9460b6955f3
--- /dev/null
+++ b/src/devices/bus/coco/dragon_msx2.cpp
@@ -0,0 +1,191 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+// thanks-to:John Whitworth
+/***************************************************************************
+
+ Dragon MSX 2+ by DragonPlus Electronics
+
+***************************************************************************/
+
+#include "emu.h"
+#include "dragon_msx2.h"
+#include "render.h"
+#include "screen.h"
+#include "speaker.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(DRAGON_MSX2, dragon_msx2_device, "dragon_msx2", "Dragon MSX 2+")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( dragon_msx2 )
+//-------------------------------------------------
+
+INPUT_PORTS_START( dragon_msx2 )
+ PORT_START("CONFIG")
+ PORT_CONFNAME(0x01, 0x00, "J1 PWR")
+ PORT_CONFSETTING(0x00, "Cart Port")
+ PORT_CONFSETTING(0x01, "External")
+ PORT_CONFNAME(0x02, 0x00, "J2 CART")
+ PORT_CONFSETTING(0x00, "N/C")
+ PORT_CONFSETTING(0x02, "HSYNC")
+ PORT_CONFNAME(0x04, 0x00, "J3 Port Select")
+ PORT_CONFSETTING(0x00, "FF7* (Native)")
+ PORT_CONFSETTING(0x04, "FF5* (MPI)")
+ PORT_CONFNAME(0x08, 0x08, "J4 Default Video")
+ PORT_CONFSETTING(0x00, "V9958")
+ PORT_CONFSETTING(0x08, "MC6847")
+ PORT_CONFNAME(0x10, 0x10, "J5 Video Lock")
+ PORT_CONFSETTING(0x00, "Locked")
+ PORT_CONFSETTING(0x10, "Unlocked")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor dragon_msx2_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( dragon_msx2 );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// dragon_msx2_device - constructor
+//-------------------------------------------------
+
+dragon_msx2_device::dragon_msx2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, DRAGON_MSX2, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this )
+ , m_ym2413(*this, "ym2413")
+ , m_v9958(*this, "v9958")
+ , m_ym2149(*this, "ym2149")
+ , m_config(*this, "CONFIG")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void dragon_msx2_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void dragon_msx2_device::device_reset()
+{
+ // pin 26 is tied to GND
+ m_ym2149->set_pin26_low_w();
+
+ // Native mode
+ if (!BIT(m_config->read(), 2))
+ {
+ install_readwrite_handler(0xff76, 0xff77, read8sm_delegate(*m_ym2413, FUNC(ym2413_device::read)), write8sm_delegate(*m_ym2413, FUNC(ym2413_device::write)));
+ install_readwrite_handler(0xff78, 0xff7b, read8sm_delegate(*m_v9958, FUNC(v9958_device::read)), write8sm_delegate(*m_v9958, FUNC(v9958_device::write)));
+ install_write_handler(0xff7c, 0xff7c, write8smo_delegate(*m_ym2149, FUNC(ym2149_device::address_w)));
+ install_readwrite_handler(0xff7d, 0xff7d, read8smo_delegate(*m_ym2149, FUNC(ym2149_device::data_r)), write8smo_delegate(*m_ym2149, FUNC(ym2149_device::data_w)));
+ install_write_handler(0xff7e, 0xff7e, write8smo_delegate(*this, FUNC(dragon_msx2_device::video_select_w)));
+ }
+
+ // Default Video
+ machine().render().first_target()->set_view(!BIT(m_config->read(), 3));
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void dragon_msx2_device::device_add_mconfig(machine_config &config)
+{
+ V9958(config, m_v9958, 21.477272_MHz_XTAL);
+ m_v9958->set_screen_pal("screen");
+ m_v9958->set_vram_size(0x20000);
+ m_v9958->int_cb().set([this](int state) { set_line_value(line::NMI, state); });
+ SCREEN(config, "screen", SCREEN_TYPE_RASTER);
+
+ SPEAKER(config, "speaker").front_center();
+ YM2413(config, m_ym2413, 21.477272_MHz_XTAL / 6).add_route(ALL_OUTPUTS, "speaker", 1.0);
+ YM2149(config, m_ym2149, 21.477272_MHz_XTAL / 6).add_route(ALL_OUTPUTS, "speaker", 1.0);
+}
+
+
+//-------------------------------------------------
+// scs_read
+//-------------------------------------------------
+
+u8 dragon_msx2_device::scs_read(offs_t offset)
+{
+ u8 data = 0x00;
+
+ if (BIT(m_config->read(), 2)) // MPI mode
+ {
+ switch (offset)
+ {
+ case 0x16: case 0x17:
+ data = m_ym2413->read(offset & 1);
+ break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ data = m_v9958->read(offset & 3);
+ break;
+
+ case 0x1d:
+ data = m_ym2149->data_r();
+ break;
+ }
+ }
+
+ return data;
+}
+
+//-------------------------------------------------
+// scs_write
+//-------------------------------------------------
+
+void dragon_msx2_device::scs_write(offs_t offset, u8 data)
+{
+ if (BIT(m_config->read(), 2)) // MPI mode
+ {
+ switch (offset)
+ {
+ case 0x16: case 0x17:
+ m_ym2413->write(offset & 1, data);
+ break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ m_v9958->write(offset & 3, data);
+ break;
+
+ case 0x1c:
+ m_ym2149->address_w(data);
+ break;
+
+ case 0x1d:
+ m_ym2149->data_w(data);
+ break;
+
+ case 0x1e:
+ video_select_w(data);
+ break;
+ }
+ }
+}
+
+void dragon_msx2_device::video_select_w(u8 data)
+{
+ if (BIT(m_config->read(), 4)) // Unlocked
+ machine().render().first_target()->set_view(!BIT(data, 0));
+}
diff --git a/src/devices/bus/coco/dragon_msx2.h b/src/devices/bus/coco/dragon_msx2.h
new file mode 100644
index 00000000000..3eb1fcaa64b
--- /dev/null
+++ b/src/devices/bus/coco/dragon_msx2.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_COCO_DRAGON_MSX2_H
+#define MAME_BUS_COCO_DRAGON_MSX2_H
+
+#pragma once
+
+#include "cococart.h"
+#include "sound/ay8910.h"
+#include "sound/ymopl.h"
+#include "video/v9938.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> dragon_msx2_device
+
+class dragon_msx2_device :
+ public device_t,
+ public device_cococart_interface
+{
+public:
+ // construction/destruction
+ dragon_msx2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual u8 scs_read(offs_t offset) override;
+ virtual void scs_write(offs_t offset, u8 data) override;
+
+private:
+ required_device<ym2413_device> m_ym2413;
+ required_device<v9958_device> m_v9958;
+ required_device<ym2149_device> m_ym2149;
+ required_ioport m_config;
+
+ void video_select_w(u8 data);
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(DRAGON_MSX2, dragon_msx2_device)
+
+#endif // MAME_BUS_COCO_DRAGON_MSX2_H
diff --git a/src/devices/bus/coco/dragon_serial.cpp b/src/devices/bus/coco/dragon_serial.cpp
new file mode 100644
index 00000000000..8967bed816c
--- /dev/null
+++ b/src/devices/bus/coco/dragon_serial.cpp
@@ -0,0 +1,154 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Peaksoft Prestel Module
+
+ Also known as the New Era Interface from Peaksoft/Harry Whitehouse, which
+ includes a through port for DOS cartridges.
+
+ TODO:
+ - RX/TX rate set by dipswitches (default 100001/001001?), for use with a 1200/75 modem.
+ - add throughport, not known how CTS/SCS lines are switched between slots.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "dragon_serial.h"
+#include "machine/clock.h"
+#include "bus/rs232/rs232.h"
+
+
+//-------------------------------------------------
+// ROM( dragon_serial )
+//-------------------------------------------------
+
+ROM_START(dragon_serial)
+ ROM_REGION(0x2000, "eprom", 0)
+ ROM_LOAD("comron_peaksoft.rom", 0x0000, 0x2000, CRC(9d18cf46) SHA1(14124dfb4bd78d1907e80d779cd7f3bae30564c9))
+ROM_END
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(DRAGON_SERIAL, dragon_serial_device, "dragon_serial", "Dragon Peaksoft Prestel Module")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// dragon_serial_device - constructor
+//-------------------------------------------------
+
+dragon_serial_device::dragon_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, DRAGON_SERIAL, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this )
+ , m_eprom(*this, "eprom")
+ , m_acia(*this, "acia")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void dragon_serial_device::device_start()
+{
+ set_line_value(line::CART, line_value::Q);
+}
+
+//-------------------------------------------------
+// dragon_serial_device::get_cart_base
+//-------------------------------------------------
+
+u8 *dragon_serial_device::get_cart_base()
+{
+ return m_eprom->base();
+}
+
+//-------------------------------------------------
+// dragon_serial_device::get_cart_memregion
+//-------------------------------------------------
+
+memory_region *dragon_serial_device::get_cart_memregion()
+{
+ return m_eprom;
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void dragon_serial_device::device_add_mconfig(machine_config &config)
+{
+ ACIA6850(config, m_acia, 0);
+ m_acia->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
+ m_acia->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts));
+ m_acia->irq_handler().set([this](int state) { set_line_value(line::NMI, state); });
+
+ clock_device &acia_clock(CLOCK(config, "acia_clock", 2.4576_MHz_XTAL));
+ acia_clock.signal_handler().set(FUNC(dragon_serial_device::write_acia_clock));
+
+ rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "null_modem"));
+ rs232.rxd_handler().set(m_acia, FUNC(acia6850_device::write_rxd));
+ rs232.cts_handler().set(m_acia, FUNC(acia6850_device::write_cts));
+ rs232.dcd_handler().set(m_acia, FUNC(acia6850_device::write_dcd));
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *dragon_serial_device::device_rom_region() const
+{
+ return ROM_NAME( dragon_serial );
+}
+
+//-------------------------------------------------
+// cts_read
+//-------------------------------------------------
+
+u8 dragon_serial_device::cts_read(offs_t offset)
+{
+ return m_eprom->base()[offset & 0x1fff];
+}
+
+//-------------------------------------------------
+// scs_read
+//-------------------------------------------------
+
+u8 dragon_serial_device::scs_read(offs_t offset)
+{
+ uint8_t result = 0x00;
+
+ switch (offset)
+ {
+ case 0x14: case 0x15:
+ result = m_acia->read(offset & 1);
+ break;
+ }
+ return result;
+}
+
+//-------------------------------------------------
+// scs_write
+//-------------------------------------------------
+
+void dragon_serial_device::scs_write(offs_t offset, u8 data)
+{
+ switch (offset)
+ {
+ case 0x14: case 0x15:
+ m_acia->write(offset & 1, data);
+ break;
+ }
+}
+
+WRITE_LINE_MEMBER(dragon_serial_device::write_acia_clock)
+{
+ m_acia->write_txc(state);
+ m_acia->write_rxc(state);
+}
diff --git a/src/devices/bus/coco/dragon_serial.h b/src/devices/bus/coco/dragon_serial.h
new file mode 100644
index 00000000000..7f33a61de67
--- /dev/null
+++ b/src/devices/bus/coco/dragon_serial.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_COCO_DRAGON_SERIAL_H
+#define MAME_BUS_COCO_DRAGON_SERIAL_H
+
+#pragma once
+
+#include "cococart.h"
+#include "machine/6850acia.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> dragon_serial_device
+
+class dragon_serial_device :
+ public device_t,
+ public device_cococart_interface
+{
+public:
+ // construction/destruction
+ dragon_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type imperfect_features() { return feature::COMMS; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual u8 *get_cart_base() override;
+ virtual memory_region *get_cart_memregion() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual u8 cts_read(offs_t offset) override;
+ virtual u8 scs_read(offs_t offset) override;
+ virtual void scs_write(offs_t offset, u8 data) override;
+
+private:
+ DECLARE_WRITE_LINE_MEMBER(write_acia_clock);
+
+ required_memory_region m_eprom;
+ required_device<acia6850_device> m_acia;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(DRAGON_SERIAL, dragon_serial_device)
+
+#endif // MAME_BUS_COCO_DRAGON_SERIAL_H
diff --git a/src/devices/bus/generic/slot.h b/src/devices/bus/generic/slot.h
index 883e521c908..ee96382f435 100644
--- a/src/devices/bus/generic/slot.h
+++ b/src/devices/bus/generic/slot.h
@@ -30,7 +30,7 @@ public:
assert(!(decode_limit & base));
for (offs_t remain = length, start = 0U; remain && (decode_limit >= start); )
{
- unsigned const msb(31 - count_leading_zeros(u32(remain)));
+ unsigned const msb(31 - count_leading_zeros_32(u32(remain)));
offs_t const chunk(offs_t(1) << msb);
offs_t range((chunk - 1) & decode_limit);
offs_t mirror(decode_limit & ~decode_mask & ~range);
diff --git a/src/devices/bus/isa/isa_cards.cpp b/src/devices/bus/isa/isa_cards.cpp
index ce23388ea1d..cc00f2233e0 100644
--- a/src/devices/bus/isa/isa_cards.cpp
+++ b/src/devices/bus/isa/isa_cards.cpp
@@ -50,6 +50,7 @@
#include "tekram_dc820.h"
#include "asc88.h"
#include "omti8621.h"
+#include "lrk330.h"
// sound
#include "adlib.h"
@@ -230,4 +231,5 @@ void pc_isa16_cards(device_slot_interface &device)
device.option_add("dc820", TEKRAM_DC820); // actually an EISA card
device.option_add("dc820b", TEKRAM_DC820B); // actually an EISA card
device.option_add("omti8621", ISA16_OMTI8621);
+ device.option_add("lrk331", LRK331);
}
diff --git a/src/devices/bus/isa/lrk330.cpp b/src/devices/bus/isa/lrk330.cpp
new file mode 100644
index 00000000000..18cd1bfe29e
--- /dev/null
+++ b/src/devices/bus/isa/lrk330.cpp
@@ -0,0 +1,130 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Skeleton driver for ESDI controllers by Lark Associates Inc.
+
+ Major ICs excluding EPROMs, in order of decreasing pin count:
+ * Silicon Logic LD1111 HDC (QFP128, U1)
+ * Xilinx XC2018-70PC68C Logic Cell Array (PLCC84, U11)
+ * National DP8473V Floppy Disk Controller PLUS-2 (PLCC52, U4)
+ * Signetics SCN8032HCCA44 8-Bit Microcontroller (PLCC44, U20)
+ * Sharp LH52258D-45 32Kx8 CMOS Static RAM (SDIP28, U2 & U3)
+ * Vitelic V61C16F70L 2Kx8 CMOS Static RAM (SSOP24, U19)
+
+ The purpose of the small SRAM is not clear. Perhaps it can be banked
+ into the lower part of the 8032 program space after loading patches
+ for the EPROM microcode, since that uses the upper mirror addresses
+ almost exclusively.
+
+ A transfer rate of up to 24 megabits per second was advertised.
+
+ LRK-330 is presumably identical to LRK-331, only without the FDC or
+ 34-pin floppy drive cable connector installed.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "lrk330.h"
+
+#include "imagedev/floppy.h"
+#include "machine/upd765.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(LRK331, lrk331_device, "lrk331", "Lark Associates LRK-331 ESDI Controller")
+
+
+lrk331_device::lrk331_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, LRK331, tag, owner, clock)
+ , device_isa16_card_interface(mconfig, *this)
+ , m_mcu(*this, "mcu")
+ , m_bios(*this, "bios")
+ , m_config(*this, "CONFIG")
+{
+}
+
+void lrk331_device::device_start()
+{
+}
+
+void lrk331_device::device_reset()
+{
+}
+
+void lrk331_device::ucode_map(address_map &map)
+{
+ map(0x0000, 0x3fff).mirror(0x4000).rom().region("ucode", 0);
+}
+
+void lrk331_device::ext_map(address_map &map)
+{
+ map.global_mask(0xff);
+ map(0x0b, 0x0b).nopw();
+}
+
+static INPUT_PORTS_START(lrk331)
+ PORT_START("CONFIG")
+ PORT_DIPNAME(0x001, 0x001, "Drive Addresses") PORT_DIPLOCATION("W1:1")
+ PORT_DIPSETTING(0x001, "Primary (1F0h-1F7h, 3F0h-3F7h)")
+ PORT_DIPSETTING(0x000, "Secondary (170h-177h, 370h-377h)")
+ PORT_DIPNAME(0x002, 0x002, "Floppy Drive Speed") PORT_DIPLOCATION("W2:2")
+ PORT_DIPSETTING(0x002, "Single")
+ PORT_DIPSETTING(0x000, "Dual")
+ PORT_DIPNAME(0x004, 0x004, "Interrupt Delay") PORT_DIPLOCATION("W3:1")
+ PORT_DIPSETTING(0x004, "Disabled")
+ PORT_DIPSETTING(0x000, "Enabled")
+ PORT_DIPNAME(0x008, 0x008, "Factory Configured - Do Not Alter") PORT_DIPLOCATION("W4:1")
+ PORT_DIPSETTING(0x008, DEF_STR(Off))
+ PORT_DIPSETTING(0x000, DEF_STR(On))
+ PORT_DIPNAME(0x0f0, 0x0e0, "BIOS Address") PORT_DIPLOCATION("W5-W8:1,2,3,4")
+ PORT_DIPSETTING(0x0f0, "Disabled")
+ PORT_DIPSETTING(0x0e0, "C800h")
+ PORT_DIPSETTING(0x0d0, "CC00h")
+ PORT_DIPSETTING(0x0b0, "D000h")
+ PORT_DIPSETTING(0x070, "D400h")
+ PORT_DIPNAME(0x300, 0x200, "IRQ Select") PORT_DIPLOCATION("W9-W10:1,2")
+ PORT_DIPSETTING(0x200, "IRQ 14")
+ PORT_DIPSETTING(0x100, "IRQ 15")
+ PORT_DIPNAME(0x400, 0x000, "Floppy Drive Interface") PORT_DIPLOCATION("W11:1")
+ PORT_DIPSETTING(0x400, "Disabled")
+ PORT_DIPSETTING(0x000, "Enabled")
+INPUT_PORTS_END
+
+ioport_constructor lrk331_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(lrk331);
+}
+
+static void pc_hd_floppies(device_slot_interface &device)
+{
+ device.option_add("525hd", FLOPPY_525_HD);
+ device.option_add("35hd", FLOPPY_35_HD);
+ device.option_add("525dd", FLOPPY_525_DD);
+ device.option_add("35dd", FLOPPY_35_DD);
+}
+
+void lrk331_device::device_add_mconfig(machine_config &config)
+{
+ I8032(config, m_mcu, 24_MHz_XTAL / 2);
+ m_mcu->set_addrmap(AS_PROGRAM, &lrk331_device::ucode_map);
+ m_mcu->set_addrmap(AS_IO, &lrk331_device::ext_map);
+
+ //LD1111(config, m_hdc, 24_MHz_XTAL);
+
+ DP8473(config, "fdc", 24_MHz_XTAL);
+ FLOPPY_CONNECTOR(config, "fdc:0", pc_hd_floppies, "525hd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:1", pc_hd_floppies, nullptr, floppy_image_device::default_pc_floppy_formats);
+}
+
+ROM_START(lrk331)
+ ROM_REGION(0x2000, "bios", 0)
+ ROM_LOAD("63308-10.bin", 0x0000, 0x2000, CRC(f16d4f25) SHA1(437664ff9723c8036a40f1e504899b7cacd21ad0))
+
+ ROM_REGION(0x4000, "ucode", 0)
+ ROM_LOAD("63307-08.bin", 0x0000, 0x4000, CRC(6d2e8b26) SHA1(1a33462a29b306b01960cf2ac0b209b2adf58dbe))
+ROM_END
+
+const tiny_rom_entry *lrk331_device::device_rom_region() const
+{
+ return ROM_NAME(lrk331);
+}
diff --git a/src/devices/bus/isa/lrk330.h b/src/devices/bus/isa/lrk330.h
new file mode 100644
index 00000000000..b75a50fa7a3
--- /dev/null
+++ b/src/devices/bus/isa/lrk330.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_ISA_LRK330_H
+#define MAME_BUS_ISA_LRK330_H
+
+#pragma once
+
+#include "isa.h"
+#include "cpu/mcs51/mcs51.h"
+
+class lrk331_device : public device_t, public device_isa16_card_interface
+{
+public:
+ lrk331_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ void ucode_map(address_map &map);
+ void ext_map(address_map &map);
+
+ required_device<mcs51_cpu_device> m_mcu;
+ required_region_ptr<u8> m_bios;
+ required_ioport m_config;
+};
+
+DECLARE_DEVICE_TYPE(LRK331, lrk331_device)
+
+#endif // MAME_BUS_ISA_LRK330_H
diff --git a/src/devices/bus/mc10/mc10_cart.cpp b/src/devices/bus/mc10/mc10_cart.cpp
new file mode 100644
index 00000000000..f7858a087bc
--- /dev/null
+++ b/src/devices/bus/mc10/mc10_cart.cpp
@@ -0,0 +1,230 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/*********************************************************************
+
+ mc10cart.cpp
+
+ MC-10 / Alice expansion slot - typically used for the 16K external
+ RAM expansion.
+
+ MC-10 and Alice pinout listing
+ --- ------- --- -------
+ 1 GND 18 A6
+ 2 GND 19 A7
+ 3 D0 20 A8
+ 4 D1 21 A9
+ 5 D2 22 A10
+ 6 D3 23 A11
+ 7 D4 24 A12
+ 8 D5 25 A13
+ 9 D6 26 A14
+ 10 D7 27 A15
+ 11 R/!W 28 E
+ 12 A0 29 SEL
+ 13 A1 30 RESET
+ 14 A2 31 !NMI
+ 15 A3 32 +5V
+ 16 A3 33 GND
+ 17 A5 34 GND
+
+ SEL is an input to the MC-10 that allows the cartridge to remove
+ the internal chips from the bus.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "mc10_cart.h"
+
+#include "mcx128.h"
+#include "pak.h"
+#include "ram.h"
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MC10CART_SLOT, mc10cart_slot_device, "mc10cart_slot", "MC-10 Cartridge Slot")
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mc10cart_slot_device - constructor
+//-------------------------------------------------
+mc10cart_slot_device::mc10cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, MC10CART_SLOT, tag, owner, clock),
+ device_single_card_slot_interface<device_mc10cart_interface>(mconfig, *this),
+ device_image_interface(mconfig, *this),
+ m_nmi_callback(*this),
+ m_cart(nullptr),
+ m_memspace(*this, finder_base::DUMMY_TAG, -1)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mc10cart_slot_device::device_start()
+{
+ m_nmi_callback.resolve_safe();
+ m_cart = get_card_device();
+}
+
+//-------------------------------------------------
+// set_nmi_line
+//-------------------------------------------------
+
+void mc10cart_slot_device::set_nmi_line(int state)
+{
+ m_nmi_callback(state);
+}
+
+//-------------------------------------------------
+// call_load
+//-------------------------------------------------
+
+image_init_result mc10cart_slot_device::call_load()
+{
+ if (!m_cart)
+ return image_init_result::PASS;
+
+ memory_region *romregion(loaded_through_softlist() ? memregion("rom") : nullptr);
+ if (loaded_through_softlist() && !romregion)
+ {
+ seterror(IMAGE_ERROR_INVALIDIMAGE, "Software list item has no 'rom' data area");
+ return image_init_result::FAIL;
+ }
+
+ u32 const len(loaded_through_softlist() ? romregion->bytes() : length());
+ if (len > m_cart->max_rom_length())
+ {
+ seterror(IMAGE_ERROR_UNSUPPORTED, "Unsupported cartridge size");
+ return image_init_result::FAIL;
+ }
+
+ if (!loaded_through_softlist())
+ {
+ LOG("Allocating %u byte cartridge ROM region\n", len);
+ romregion = machine().memory().region_alloc(subtag("rom").c_str(), len, 1, ENDIANNESS_BIG);
+ u32 const cnt(fread(romregion->base(), len));
+ if (cnt != len)
+ {
+ seterror(IMAGE_ERROR_UNSPECIFIED, "Error reading cartridge file");
+ return image_init_result::FAIL;
+ }
+ }
+
+ return m_cart->load();
+}
+
+//-------------------------------------------------
+// get_default_card_software
+//-------------------------------------------------
+
+std::string mc10cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ return software_get_default_slot("pak");
+}
+
+//**************************************************************************
+// DEVICE MC-10 CART INTERFACE - Implemented by devices that plug into
+// MC-10 cartridge slots
+//**************************************************************************
+
+template class device_finder<device_mc10cart_interface, false>;
+template class device_finder<device_mc10cart_interface, true>;
+
+//-------------------------------------------------
+// device_mc10cart_interface - constructor
+//-------------------------------------------------
+
+device_mc10cart_interface::device_mc10cart_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "mc10cart")
+ , m_owning_slot(nullptr)
+{
+}
+
+//-------------------------------------------------
+// ~device_mc10cart_interface - destructor
+//-------------------------------------------------
+
+device_mc10cart_interface::~device_mc10cart_interface()
+{
+}
+
+//-------------------------------------------------
+// interface_config_complete
+//-------------------------------------------------
+
+void device_mc10cart_interface::interface_config_complete()
+{
+ m_owning_slot = dynamic_cast<mc10cart_slot_device *>(device().owner());
+}
+
+//-------------------------------------------------
+// interface_pre_start
+//-------------------------------------------------
+
+void device_mc10cart_interface::interface_pre_start()
+{
+ if (!m_owning_slot)
+ throw emu_fatalerror("Expected device().owner() to be of type mc10cart_slot_device");
+}
+
+/*-------------------------------------------------
+ max_rom_length
+-------------------------------------------------*/
+
+int device_mc10cart_interface::max_rom_length() const
+{
+ return 0;
+}
+
+/*-------------------------------------------------
+ load
+-------------------------------------------------*/
+
+image_init_result device_mc10cart_interface::load()
+{
+ return image_init_result::FAIL;
+}
+
+//-------------------------------------------------
+// mc10_cart_add_basic_devices
+//-------------------------------------------------
+
+void mc10_cart_add_basic_devices(device_slot_interface &device)
+{
+ // basic devices
+ device.option_add("mcx128", MC10_PAK_MCX128);
+ device.option_add("pak", MC10_PAK);
+ device.option_add("ram", MC10_PAK_RAM);
+}
+
+//-------------------------------------------------
+// alice_cart_add_basic_devices
+//-------------------------------------------------
+
+void alice_cart_add_basic_devices(device_slot_interface &device)
+{
+ // basic devices
+ device.option_add("alice128", ALICE_PAK_MCX128);
+ device.option_add("pak", MC10_PAK);
+ device.option_add("ram", MC10_PAK_RAM);
+}
+
+//-------------------------------------------------
+// alice32_cart_add_basic_devices
+//-------------------------------------------------
+
+void alice32_cart_add_basic_devices(device_slot_interface &device)
+{
+ // basic devices
+ device.option_add("pak", MC10_PAK);
+ device.option_add("ram", MC10_PAK_RAM);
+}
diff --git a/src/devices/bus/mc10/mc10_cart.h b/src/devices/bus/mc10/mc10_cart.h
new file mode 100644
index 00000000000..eba93284325
--- /dev/null
+++ b/src/devices/bus/mc10/mc10_cart.h
@@ -0,0 +1,118 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/*********************************************************************
+
+ mc10_cart.h
+
+ MC-10 / Alice cartridge management
+
+*********************************************************************/
+
+#ifndef MAME_BUS_MC10_MC10CART_H
+#define MAME_BUS_MC10_MC10CART_H
+
+#pragma once
+
+#include "softlist_dev.h"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> mc10cart_slot_device
+class device_mc10cart_interface;
+
+class mc10cart_slot_device final : public device_t,
+ public device_single_card_slot_interface<device_mc10cart_interface>,
+ public device_image_interface
+{
+public:
+
+ // construction/destruction
+ template <typename T>
+ mc10cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&opts, const char *dflt)
+ : mc10cart_slot_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ mc10cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // inline configuration
+ template <typename T> void set_memspace(T &&tag, int spacenum) { m_memspace.set_tag(std::forward<T>(tag), spacenum); }
+ auto nmi_callback() { return m_nmi_callback.bind(); }
+
+ // address map manipulations
+ address_space &memspace() const { return *m_memspace; };
+
+ // device-level overrides
+ virtual void device_start() override;
+
+ // image-level overrides
+ virtual image_init_result call_load() override;
+ virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+
+ virtual iodevice_t image_type() const noexcept override { return IO_CARTSLOT; }
+
+ virtual bool is_readable() const noexcept override { return true; }
+ virtual bool is_writeable() const noexcept override { return false; }
+ virtual bool is_creatable() const noexcept override { return false; }
+ virtual bool must_be_loaded() const noexcept override { return false; }
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+ virtual const char *image_interface() const noexcept override { return "mc10_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "mcc,rom"; }
+
+ // manipulation of nmi line
+ void set_nmi_line(int state);
+ devcb_write_line m_nmi_callback;
+
+ // slot interface overrides
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+
+private:
+
+ // cartridge
+ device_mc10cart_interface *m_cart;
+
+protected:
+ required_address_space m_memspace;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(MC10CART_SLOT, mc10cart_slot_device)
+
+class device_mc10cart_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_mc10cart_interface();
+
+ virtual int max_rom_length() const;
+ virtual image_init_result load();
+
+protected:
+ void raise_cart_nmi() { m_owning_slot->set_nmi_line(ASSERT_LINE); }
+ void lower_cart_nmi() { m_owning_slot->set_nmi_line(CLEAR_LINE); }
+
+ virtual void interface_config_complete() override;
+ virtual void interface_pre_start() override;
+
+ device_mc10cart_interface(const machine_config &mconfig, device_t &device);
+
+ // accessors for containers
+ mc10cart_slot_device &owning_slot() const { assert(m_owning_slot); return *m_owning_slot; }
+
+private:
+ mc10cart_slot_device * m_owning_slot;
+};
+
+// methods for configuring MC-10 slot devices
+void mc10_cart_add_basic_devices(device_slot_interface &device);
+void alice_cart_add_basic_devices(device_slot_interface &device);
+void alice32_cart_add_basic_devices(device_slot_interface &device);
+
+#endif // MAME_BUS_MC10_MC10CART_H
diff --git a/src/devices/bus/mc10/mcx128.cpp b/src/devices/bus/mc10/mcx128.cpp
new file mode 100644
index 00000000000..32c9239afb5
--- /dev/null
+++ b/src/devices/bus/mc10/mcx128.cpp
@@ -0,0 +1,371 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/***************************************************************************
+
+ mcx128.cpp
+
+ Code for emulating Darren Atkinson's MCX-128 cartridge
+
+ Features:
+ 128K of RAM expansion
+ 16K of ROM expansion
+
+ New MC-10 memory map defined by this cartridge:
+
+ 0000 - 0003 6803 Ports
+ 0004 - 0007 Expansion RAM
+ 0008 - 000E 6803 Status / Control
+ 000F Expansion RAM
+ 0010 - 0013 6803 UART
+ 0014 6803 RAM Control Reg
+ 0015 - 001F Unused
+ 0020 - 007F Expansion RAM
+ 0080 - 00FF On-chip CPU RAM / Expansion RAM
+ 0100 - 3FFF Expansion RAM
+ 4000 - 5FFF Built-In RAM / Expansion RAM
+ 6000 - BEFF Expansion RAM
+ BF00 RAM Bank Control Reg
+ BF01 ROM Map Control Reg
+ BF80 - BFFF Keyboard / VDG / Sound
+ C000 - DFFF EPROM or Expansion RAM
+ E000 - FFFF Built-in ROM, EPROM or Expansion RAM
+
+ Deficiency:
+
+ * Writing to 6803 chip RAM at $80 to $ff should be mirrored
+ to external RAM.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mcx128.h"
+
+//#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+
+ROM_START(mc10_mcx128)
+ ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00)
+ ROM_LOAD("mcx128bas.rom", 0x0000, 0x4000, CRC(11202e4b) SHA1(36c30d0f198a1bffee88ef29d92f2401447a91f4))
+ROM_END
+
+ROM_START(alice_mcx128)
+ ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00)
+ ROM_LOAD("alice128bas.rom", 0x0000, 0x4000, CRC(a737544a) SHA1(c8fd92705fc42deb6a0ffac6274e27fd61ecd4cc))
+ROM_END
+
+//**************************************************************************
+// TYPE DECLARATIONS
+//**************************************************************************
+
+// ======================> mc10_pak_device
+
+class mc10_pak_mcx128_device :
+ public device_t,
+ public device_mc10cart_interface
+{
+public:
+ // construction/destruction
+ mc10_pak_mcx128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // construction/destruction
+ mc10_pak_mcx128_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_post_load() override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME(mc10_mcx128);
+ }
+
+ u8 control_register_read(offs_t offset);
+ void control_register_write(offs_t offset, u8 data);
+
+ void write_ram_mirror(address_space &space, offs_t offset, u8 data);
+
+ void view_map0(address_map &map);
+ void view_map1(address_map &map);
+ void view_map2(address_map &map);
+ void view_map3(address_map &map);
+ void view_map4(address_map &map);
+ void view_map5(address_map &map);
+ void view_map6(address_map &map);
+ void view_map7(address_map &map);
+
+
+private:
+ memory_share_creator<u8> m_share;
+ memory_view m_view;
+ memory_bank_array_creator<8> m_bank;
+ uint8_t ram_bank_cr;
+ uint8_t rom_map_cr;
+
+ void update_banks();
+
+};
+
+DEFINE_DEVICE_TYPE_PRIVATE(MC10_PAK_MCX128, device_mc10cart_interface, mc10_pak_mcx128_device, "mc10_mcx128", "Darren Atkinson's MCX-128 cartridge")
+
+//-------------------------------------------------
+// mc10_pak_device - constructor
+//-------------------------------------------------
+
+mc10_pak_mcx128_device::mc10_pak_mcx128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ :mc10_pak_mcx128_device(mconfig, MC10_PAK_MCX128, tag, owner, clock)
+{
+}
+
+mc10_pak_mcx128_device::mc10_pak_mcx128_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_mc10cart_interface(mconfig, *this)
+ , m_share(*this, "ext_ram", 1024*128, ENDIANNESS_BIG)
+ , m_view(*this, "mcx_view")
+ , m_bank(*this, "bank%u", 0U)
+{
+}
+
+void mc10_pak_mcx128_device::view_map0(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0x5fff).bankr("bank3").w(FUNC(mc10_pak_mcx128_device::write_ram_mirror));
+ map(0x6000, 0xbeff).bankrw("bank4");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xfeff).rom().region("eprom",0x0000).bankw("bank5");
+ map(0xff00, 0xffff).rom().region("eprom",0x3f00).bankw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map1(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0x5fff).bankr("bank3").w(FUNC(mc10_pak_mcx128_device::write_ram_mirror));
+ map(0x6000, 0xbeff).bankrw("bank4");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xdfff).bankrw("bank5");
+ map(0xe000, 0xfeff).rom().region("eprom",0x2000).bankw("bank6");
+ map(0xff00, 0xffff).rom().region("eprom",0x3f00).bankw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map2(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0x5fff).bankr("bank3").w(FUNC(mc10_pak_mcx128_device::write_ram_mirror));
+ map(0x6000, 0xbeff).bankrw("bank4");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xdfff).bankrw("bank5");
+ map(0xe000, 0xfeff).bankw("bank6");
+ map(0xff00, 0xffff).bankw("bank7");
+// 0xe000, 0xffff: read internal ROM
+}
+
+void mc10_pak_mcx128_device::view_map3(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0x5fff).bankr("bank3").w(FUNC(mc10_pak_mcx128_device::write_ram_mirror));
+ map(0x6000, 0xbeff).bankrw("bank4");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xfeff).bankrw("bank5");
+ map(0xff00, 0xffff).bankrw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map4(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0xbeff).bankrw("bank3");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xfeff).rom().region("eprom",0x0000).bankw("bank5");
+ map(0xff00, 0xffff).rom().region("eprom",0x3f00).bankw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map5(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0xbeff).bankrw("bank3");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xdfff).bankrw("bank5");
+ map(0xe000, 0xfeff).rom().region("eprom",0x2000).bankw("bank6");
+ map(0xff00, 0xffff).rom().region("eprom",0x3f00).bankw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map6(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0xbeff).bankrw("bank3");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xdfff).bankrw("bank5");
+ map(0xe000, 0xfeff).bankw("bank6");
+ map(0xff00, 0xffff).bankw("bank7");
+// 0xe000, 0xffff: read internal ROM
+}
+
+void mc10_pak_mcx128_device::view_map7(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0xbeff).bankrw("bank3");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xfeff).bankrw("bank5");
+ map(0xff00, 0xffff).bankrw("bank7");
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mc10_pak_mcx128_device::device_start()
+{
+ save_item(NAME(ram_bank_cr));
+ save_item(NAME(rom_map_cr));
+
+ // 0x0004 - 0x0007
+ m_bank[0]->configure_entry(0, &m_share[0x00004]);
+ m_bank[0]->configure_entry(1, &m_share[0x10004]);
+
+ // 0x000f - 0x000f
+ m_bank[1]->configure_entry(0, &m_share[0x0000f]);
+ m_bank[1]->configure_entry(1, &m_share[0x1000f]);
+
+ // 0x0000 - 0x3fff
+ m_bank[2]->configure_entry(0, &m_share[0x00020]);
+ m_bank[2]->configure_entry(1, &m_share[0x10020]);
+
+ // 0x4000 - 0x5fff
+ m_bank[3]->configure_entry(0, &m_share[0x08000]);
+ m_bank[3]->configure_entry(1, &m_share[0x18000]);
+
+ // 0x6000 - 0xbeff
+ m_bank[4]->configure_entry(0, &m_share[0x0a000]);
+ m_bank[4]->configure_entry(1, &m_share[0x1a000]);
+
+ // 0xc000 - 0xdfff
+ m_bank[5]->configure_entry(0, &m_share[0x04000]);
+ m_bank[5]->configure_entry(1, &m_share[0x14000]);
+
+ // 0xe000 - 0xffff
+ m_bank[6]->configure_entry(0, &m_share[0x06000]);
+ m_bank[6]->configure_entry(1, &m_share[0x16000]);
+
+ // 0xff00 - 0xffff
+ m_bank[7]->configure_entry(0, &m_share[0x07f00]);
+ m_bank[7]->configure_entry(1, &m_share[0x07f00]);
+
+ owning_slot().memspace().install_view(0x0000, 0xffff, m_view);
+
+ m_view[0].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map0);
+ m_view[1].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map1);
+ m_view[2].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map2);
+ m_view[3].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map3);
+ m_view[4].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map4);
+ m_view[5].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map5);
+ m_view[6].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map6);
+ m_view[7].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map7);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific startup
+//-------------------------------------------------
+
+void mc10_pak_mcx128_device::device_reset()
+{
+ ram_bank_cr = 0;
+ rom_map_cr = 0;
+ update_banks();
+}
+
+void mc10_pak_mcx128_device::device_post_load()
+{
+ update_banks();
+}
+
+void mc10_pak_mcx128_device::write_ram_mirror(address_space &space, offs_t offset, u8 data)
+{
+ std::optional<int> cur_slot = m_view.entry();
+ m_share[0x08000+offset] = data;
+
+ if (cur_slot.has_value())
+ {
+ int cur_slot_int = *cur_slot;
+ m_view.disable();
+ space.write_byte(0x4000+offset, data);
+ m_view.select(cur_slot_int);
+ }
+}
+
+u8 mc10_pak_mcx128_device::control_register_read(offs_t offset)
+{
+ if (offset==0)
+ return ram_bank_cr & 0x03;
+
+ return rom_map_cr & 0x03;
+}
+
+void mc10_pak_mcx128_device::control_register_write(offs_t offset, u8 data)
+{
+ if (offset==0)
+ ram_bank_cr = data;
+ else
+ rom_map_cr = data;
+
+ update_banks();
+}
+
+void mc10_pak_mcx128_device::update_banks()
+{
+ int bank0 = ram_bank_cr & 0x01;
+ int bank1 = (ram_bank_cr & 0x02) >> 1;
+
+ m_bank[0]->set_entry(bank0);
+ m_bank[1]->set_entry(bank0);
+ m_bank[2]->set_entry(bank0);
+ m_bank[3]->set_entry(bank1);
+ m_bank[4]->set_entry(bank1);
+ m_bank[5]->set_entry(bank0);
+ m_bank[6]->set_entry(bank0);
+ m_bank[7]->set_entry(bank0);
+
+ m_view.select((bank1 << 2) | (rom_map_cr & 0x03));
+ LOG("view select: %d, bank cr: %d\n", (bank1 << 2) | (rom_map_cr & 0x03), ram_bank_cr & 0x03 );
+}
+
+class alice_pak_mcx128_device : public mc10_pak_mcx128_device
+{
+public:
+ // construction/destruction
+ alice_pak_mcx128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME(alice_mcx128);
+ }
+};
+
+//-------------------------------------------------
+// mc10_pak_device - constructor
+//-------------------------------------------------
+
+alice_pak_mcx128_device::alice_pak_mcx128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : mc10_pak_mcx128_device(mconfig, ALICE_PAK_MCX128, tag, owner, clock)
+{
+}
+
+DEFINE_DEVICE_TYPE_PRIVATE(ALICE_PAK_MCX128, device_mc10cart_interface, alice_pak_mcx128_device, "alice_mcx128", "Darren Atkinson's MCX-128 cartridge (Alice ROM)")
diff --git a/src/devices/bus/mc10/mcx128.h b/src/devices/bus/mc10/mcx128.h
new file mode 100644
index 00000000000..29ae63b64e2
--- /dev/null
+++ b/src/devices/bus/mc10/mcx128.h
@@ -0,0 +1,15 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+#ifndef MAME_BUS_MC10_MC10_MCX128_H
+#define MAME_BUS_MC10_MC10_MCX128_H
+
+#pragma once
+
+#include "mc10_cart.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(MC10_PAK_MCX128, device_mc10cart_interface)
+DECLARE_DEVICE_TYPE(ALICE_PAK_MCX128, device_mc10cart_interface)
+
+#endif // MAME_BUS_MC10_MC10_MCX128_H
+
diff --git a/src/devices/bus/mc10/pak.cpp b/src/devices/bus/mc10/pak.cpp
new file mode 100644
index 00000000000..8e27d58ab8b
--- /dev/null
+++ b/src/devices/bus/mc10/pak.cpp
@@ -0,0 +1,69 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/***************************************************************************
+
+ pak.cpp
+
+ Code for emulating standard MC-10 cartridges with only ROM
+
+***************************************************************************/
+
+#include "emu.h"
+#include "pak.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MC10_PAK, mc10_pak_device, "mc10pak", "MC-10 Program PAK")
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mc10_pak_device - constructor
+//-------------------------------------------------
+mc10_pak_device::mc10_pak_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_mc10cart_interface(mconfig, *this)
+{
+}
+
+mc10_pak_device::mc10_pak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : mc10_pak_device(mconfig, MC10_PAK, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// max_rom_length - device-specific startup
+//-------------------------------------------------
+
+int mc10_pak_device::max_rom_length() const
+{
+ return 1024 * 16;
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mc10_pak_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// load - install rom region
+//-------------------------------------------------
+
+image_init_result mc10_pak_device::load()
+{
+ // if the host has supplied a ROM space, install it
+ memory_region *const romregion(memregion("^rom"));
+ if (romregion)
+ owning_slot().memspace().install_rom(0x5000, 0x5000 + romregion->bytes(), romregion->base());
+ else
+ return image_init_result::FAIL;
+
+ return image_init_result::PASS;
+}
diff --git a/src/devices/bus/mc10/pak.h b/src/devices/bus/mc10/pak.h
new file mode 100644
index 00000000000..797cea2f691
--- /dev/null
+++ b/src/devices/bus/mc10/pak.h
@@ -0,0 +1,37 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+#ifndef MAME_BUS_MC10_MC10_PAK_H
+#define MAME_BUS_MC10_MC10_PAK_H
+
+#pragma once
+
+#include "mc10_cart.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mc10_pak_device
+
+class mc10_pak_device :
+ public device_t,
+ public device_mc10cart_interface
+{
+public:
+ // construction/destruction
+ mc10_pak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual int max_rom_length() const override;
+ virtual image_init_result load() override;
+
+protected:
+ mc10_pak_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+};
+
+// device type definitions
+DECLARE_DEVICE_TYPE(MC10_PAK, mc10_pak_device)
+
+#endif // MAME_BUS_MC10_MC10_PAK_H
diff --git a/src/devices/bus/mc10/ram.cpp b/src/devices/bus/mc10/ram.cpp
new file mode 100644
index 00000000000..f6a6f488955
--- /dev/null
+++ b/src/devices/bus/mc10/ram.cpp
@@ -0,0 +1,78 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/***************************************************************************
+
+ ram.cpp
+
+ Code for emulating the Radio Shack 16K RAM Cartridge
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ram.h"
+
+// #include "machine/ram.h"
+
+// #define VERBOSE (LOG_GENERAL )
+#include "logmacro.h"
+
+
+//**************************************************************************
+// TYPE DECLARATIONS
+//**************************************************************************
+
+namespace
+{
+ // ======================> mc10_pak_device
+
+ class mc10_pak_ram_device :
+ public device_t,
+ public device_mc10cart_interface
+ {
+ public:
+ // construction/destruction
+ mc10_pak_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ protected:
+ // device-level overrides
+ virtual void device_start() override;
+ private:
+ memory_share_creator<u8> m_share;
+ };
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(MC10_PAK_RAM, device_mc10cart_interface, mc10_pak_ram_device, "mc10pakram", "Radio Shack 16K RAM Cartridge")
+
+
+
+//-------------------------------------------------
+// mc10_pak_device - constructor
+//-------------------------------------------------
+
+mc10_pak_ram_device::mc10_pak_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MC10_PAK_RAM, tag, owner, clock)
+ , device_mc10cart_interface(mconfig, *this)
+ , m_share(*this, "ext_ram", 1024*16, ENDIANNESS_BIG)
+{
+}
+
+
+
+//**************************************************************************
+// MACHINE FRAGMENTS AND ADDRESS MAPS
+//**************************************************************************
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mc10_pak_ram_device::device_start()
+{
+ owning_slot().memspace().install_ram(0x5000, 0x8fff, &m_share[0]);
+}
diff --git a/src/devices/bus/mc10/ram.h b/src/devices/bus/mc10/ram.h
new file mode 100644
index 00000000000..e32530f81e6
--- /dev/null
+++ b/src/devices/bus/mc10/ram.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+#ifndef MAME_BUS_MC10_MC10_RAM_H
+#define MAME_BUS_MC10_MC10_RAM_H
+
+#pragma once
+
+#include "mc10_cart.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(MC10_PAK_RAM, device_mc10cart_interface)
+
+#endif // MAME_BUS_MC10_MC10_RAM_H
+
diff --git a/src/devices/bus/nes/act53.cpp b/src/devices/bus/nes/act53.cpp
index 2a441c36153..0576f36a06c 100644
--- a/src/devices/bus/nes/act53.cpp
+++ b/src/devices/bus/nes/act53.cpp
@@ -32,7 +32,7 @@
DEFINE_DEVICE_TYPE(NES_ACTION53, nes_action53_device, "nes_action53", "NES Cart Action 53 PCB")
-nes_action53_device::nes_action53_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_action53_device::nes_action53_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_ACTION53, tag, owner, clock)
, m_sel(0)
{
@@ -45,17 +45,21 @@ void nes_action53_device::device_start()
common_start();
save_item(NAME(m_sel));
save_item(NAME(m_reg));
- m_reg[0] = 0x00;
- m_reg[1] = 0x0f;
- m_reg[2] = 0x00;
- m_reg[3] = 0x3f;
+}
+
+void nes_action53_device::pcb_start(running_machine &machine, u8 *ciram_ptr, bool cart_mounted)
+{
+ device_nes_cart_interface::pcb_start(machine, ciram_ptr, cart_mounted);
+ // at power on last 16K of ROM is mapped to $C000-$FFFF
+ m_reg[0] = m_reg[1] = m_reg[2] = 0;
+ m_reg[3] = (m_prg_chunks - 1) >> 1;
+ update_prg();
}
void nes_action53_device::pcb_reset()
{
m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
// register content is not touched by reset
- update_prg();
}
@@ -79,7 +83,7 @@ void nes_action53_device::pcb_reset()
R:$80 is clear
R:$01: [...M PPPP]
- P = PRG Reg
+ P = Inner PRG Reg
M = Mirroring
This bit overwrites bit 0 of R:$80, but only if bit 1 of
R:$80 is clear
@@ -97,7 +101,7 @@ void nes_action53_device::pcb_reset()
%10 = Vert
%11 = Horz
- R:$81: [..BB BBBB]
+ R:$81: [BBBB BBBB]
Outer PRG Reg
@@ -105,34 +109,20 @@ void nes_action53_device::pcb_reset()
void nes_action53_device::update_prg()
{
- uint8_t prg_lo, prg_hi, helper;
- uint8_t out = (m_reg[3] & 0x3f) << 1; // Outer PRG reg
- uint8_t size = (m_reg[2] & 0x30) >> 4; // Game size
- uint8_t mask = (1 << (size + 1)) - 1; // Bits to be taken from PRG reg
-
- if (!BIT(m_reg[2], 3))
- {
- helper = (out & ~mask) | ((m_reg[1] << 1) & mask);
- //32K mode
- prg_lo = (helper & 0xfe);
- prg_hi = (helper | 0x01);
- }
- else
- {
- helper = (out & ~mask) | (m_reg[1] & mask);
- if (BIT(m_reg[2], 2))
- {
- //16K mode with fixed HI
- prg_lo = helper;
- prg_hi = (out | 0x01);
- }
- else
- {
- //16K mode with fixed LO
- prg_lo = (out & 0xfe);
- prg_hi = helper;
- }
- }
+ u16 prg_lo, prg_hi;
+ u8 size = (m_reg[2] & 0x30) >> 4; // Game size
+ u16 mask = ~0 << (size + 1); // Bits to be taken from PRG regs
+ u8 b32k = !BIT(m_reg[2], 3); // 32K mode bit
+ u16 outer = m_reg[3] << 1; // Outer PRG reg bits
+ u8 inner = (m_reg[1] << b32k) & ~mask; // Inner PRG reg bits
+
+ prg_hi = prg_lo = (outer & mask) | inner;
+ if (b32k) // 32K mode
+ prg_hi++;
+ else if (BIT(m_reg[2], 2)) // 16K mode with fixed HI
+ prg_hi = ++outer;
+ else // 16K mode with fixed LO
+ prg_lo = outer;
// printf("banks : 0x%2X - 0x%2X\n", prg_lo, prg_hi);
prg16_89ab(prg_lo);
@@ -158,7 +148,7 @@ void nes_action53_device::update_mirr()
}
}
-void nes_action53_device::write_l(offs_t offset, uint8_t data)
+void nes_action53_device::write_l(offs_t offset, u8 data)
{
LOG_MMC(("action 53 write_l, offset: %04x, data: %02x\n", offset, data));
offset += 0x100;
@@ -167,7 +157,7 @@ void nes_action53_device::write_l(offs_t offset, uint8_t data)
}
-void nes_action53_device::write_h(offs_t offset, uint8_t data)
+void nes_action53_device::write_h(offs_t offset, u8 data)
{
LOG_MMC(("action 53 write_h, offset: %04x, data: %02x\n", offset, data));
diff --git a/src/devices/bus/nes/act53.h b/src/devices/bus/nes/act53.h
index 8e4b1c3b073..ead18a54ad6 100644
--- a/src/devices/bus/nes/act53.h
+++ b/src/devices/bus/nes/act53.h
@@ -12,12 +12,13 @@ class nes_action53_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_action53_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_action53_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
+ virtual void pcb_start(running_machine &machine, u8 *ciram_ptr, bool cart_mounted) override;
protected:
// device-level overrides
@@ -26,8 +27,8 @@ protected:
private:
void update_prg();
void update_mirr();
- uint8_t m_sel;
- uint8_t m_reg[4];
+ u8 m_sel;
+ u8 m_reg[4];
};
// device type definition
diff --git a/src/devices/bus/nes/nes_slot.h b/src/devices/bus/nes/nes_slot.h
index acdfed33164..a207a26e869 100644
--- a/src/devices/bus/nes/nes_slot.h
+++ b/src/devices/bus/nes/nes_slot.h
@@ -237,9 +237,9 @@ protected:
device_nes_cart_interface(const machine_config &mconfig, device_t &device);
DECLARE_WRITE_LINE_MEMBER(set_irq_line);
- void hold_irq_line();
+ [[deprecated("IRQs should be cleared explicitly")]] void hold_irq_line();
void reset_cpu();
- void poke(offs_t offset, uint8_t data);
+ [[deprecated("devices should stop poking into memory spaces where they don't belong")]] void poke(offs_t offset, uint8_t data);
// internal state
uint8_t *m_prg;
diff --git a/src/devices/bus/newbrain/eim.cpp b/src/devices/bus/newbrain/eim.cpp
index be3cae2e615..7b3685eeea7 100644
--- a/src/devices/bus/newbrain/eim.cpp
+++ b/src/devices/bus/newbrain/eim.cpp
@@ -113,7 +113,7 @@ newbrain_eim_device::newbrain_eim_device(const machine_config &mconfig, const ch
device_newbrain_expansion_slot_interface(mconfig, *this),
m_ctc(*this, Z80CTC_TAG),
m_acia(*this, MC6850_TAG),
- m_exp(*this, NEWBRAIN_EXPANSION_SLOT_TAG),
+ m_exp(*this, "exp"),
m_rom(*this, "eim"),
m_ram(*this, RAM_TAG)
{
diff --git a/src/devices/bus/newbrain/exp.h b/src/devices/bus/newbrain/exp.h
index e8293a9c540..922ef17213a 100644
--- a/src/devices/bus/newbrain/exp.h
+++ b/src/devices/bus/newbrain/exp.h
@@ -43,13 +43,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define NEWBRAIN_EXPANSION_SLOT_TAG "exp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/newbrain/fdc.cpp b/src/devices/bus/newbrain/fdc.cpp
index a356d034a39..fa046e0d5a9 100644
--- a/src/devices/bus/newbrain/fdc.cpp
+++ b/src/devices/bus/newbrain/fdc.cpp
@@ -135,11 +135,8 @@ newbrain_fdc_device::newbrain_fdc_device(const machine_config &mconfig, const ch
device_newbrain_expansion_slot_interface(mconfig, *this),
m_maincpu(*this, Z80_TAG),
m_fdc(*this, UPD765_TAG),
- m_floppy0(*this, UPD765_TAG ":0"),
- m_floppy1(*this, UPD765_TAG ":1"),
- m_floppy2(*this, UPD765_TAG ":2"),
- m_floppy3(*this, UPD765_TAG ":3"),
- m_exp(*this, NEWBRAIN_EXPANSION_SLOT_TAG)
+ m_floppy(*this, UPD765_TAG ":%u", 0U),
+ m_exp(*this, "exp")
{
}
@@ -224,10 +221,9 @@ void newbrain_fdc_device::iorq_w(offs_t offset, uint8_t data, bool &prtov)
void newbrain_fdc_device::moton(int state)
{
- if (m_floppy0->get_device()) m_floppy0->get_device()->mon_w(!state);
- if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(!state);
- if (m_floppy2->get_device()) m_floppy2->get_device()->mon_w(!state);
- if (m_floppy3->get_device()) m_floppy3->get_device()->mon_w(!state);
+ for (auto &floppy : m_floppy)
+ if (floppy->get_device())
+ floppy->get_device()->mon_w(!state);
}
diff --git a/src/devices/bus/newbrain/fdc.h b/src/devices/bus/newbrain/fdc.h
index e5d6665a078..3ac24faffa6 100644
--- a/src/devices/bus/newbrain/fdc.h
+++ b/src/devices/bus/newbrain/fdc.h
@@ -57,10 +57,7 @@ private:
required_device<z80_device> m_maincpu;
required_device<upd765a_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
- required_device<floppy_connector> m_floppy2;
- required_device<floppy_connector> m_floppy3;
+ required_device_array<floppy_connector, 4> m_floppy;
required_device<newbrain_expansion_slot_device> m_exp;
void moton(int state);
diff --git a/src/devices/bus/odyssey2/rom.cpp b/src/devices/bus/odyssey2/rom.cpp
index 20b04256d00..b964d99b584 100644
--- a/src/devices/bus/odyssey2/rom.cpp
+++ b/src/devices/bus/odyssey2/rom.cpp
@@ -28,7 +28,7 @@ void o2_rom_device::device_start()
void o2_rom_device::cart_init()
{
- m_cart_mask = (1 << (31 - count_leading_zeros(m_rom_size))) - 1;
+ m_cart_mask = (1 << (31 - count_leading_zeros_32(m_rom_size))) - 1;
}
diff --git a/src/devices/bus/pet/exp.h b/src/devices/bus/pet/exp.h
index d3adf1e9262..14fe9296a8d 100644
--- a/src/devices/bus/pet/exp.h
+++ b/src/devices/bus/pet/exp.h
@@ -17,13 +17,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define PET_EXPANSION_SLOT_TAG "exp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/plus4/c1551.cpp b/src/devices/bus/plus4/c1551.cpp
index 5811f7b42f7..b8ecd0b7642 100644
--- a/src/devices/bus/plus4/c1551.cpp
+++ b/src/devices/bus/plus4/c1551.cpp
@@ -368,7 +368,7 @@ void c1551_device::device_add_mconfig(machine_config &config)
connector.set_fixed(true);
connector.set_formats(c1551_device::floppy_formats);
- PLUS4_EXPANSION_SLOT(config, m_exp, 0);
+ PLUS4_EXPANSION_SLOT(config, m_exp, DERIVED_CLOCK(1, 1));
m_exp->irq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(plus4_expansion_slot_device::irq_w));
m_exp->cd_rd_callback().set(DEVICE_SELF_OWNER, FUNC(plus4_expansion_slot_device::dma_cd_r));
m_exp->cd_wr_callback().set(DEVICE_SELF_OWNER, FUNC(plus4_expansion_slot_device::dma_cd_w));
@@ -417,7 +417,7 @@ c1551_device::c1551_device(const machine_config &mconfig, const char *tag, devic
, m_ga(*this, C64H156_TAG)
, m_pla(*this, PLA_TAG)
, m_floppy(*this, C64H156_TAG":0:525ssqd")
- , m_exp(*this, PLUS4_EXPANSION_SLOT_TAG)
+ , m_exp(*this, "exp")
, m_jp1(*this, "JP1")
, m_leds(*this, "led%u", 0U)
, m_tcbm_data(0xff)
diff --git a/src/devices/bus/plus4/exp.cpp b/src/devices/bus/plus4/exp.cpp
index 4099b38d5bd..fb0387908ef 100644
--- a/src/devices/bus/plus4/exp.cpp
+++ b/src/devices/bus/plus4/exp.cpp
@@ -90,15 +90,6 @@ void plus4_expansion_slot_device::device_start()
m_read_dma_cd.resolve_safe(0xff);
m_write_dma_cd.resolve_safe();
m_write_aec.resolve_safe();
-
- // inherit bus clock
- // FIXME: this should be unnecessary as slots pass DERIVED_CLOCK(1, 1) through by default
- if (clock() == 0)
- {
- plus4_expansion_slot_device *root = machine().root_device().subdevice<plus4_expansion_slot_device>(PLUS4_EXPANSION_SLOT_TAG);
- assert(root);
- set_unscaled_clock(root->clock());
- }
}
diff --git a/src/devices/bus/plus4/exp.h b/src/devices/bus/plus4/exp.h
index fb03fb7fd4b..785207dd4f1 100644
--- a/src/devices/bus/plus4/exp.h
+++ b/src/devices/bus/plus4/exp.h
@@ -43,13 +43,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define PLUS4_EXPANSION_SLOT_TAG "exp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/pofo/exp.h b/src/devices/bus/pofo/exp.h
index f760ce694c3..4078535e2c7 100644
--- a/src/devices/bus/pofo/exp.h
+++ b/src/devices/bus/pofo/exp.h
@@ -48,13 +48,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define PORTFOLIO_EXPANSION_SLOT_TAG "exp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/pofo/hpc104.cpp b/src/devices/bus/pofo/hpc104.cpp
index 11744206c7e..0d8953b20c6 100644
--- a/src/devices/bus/pofo/hpc104.cpp
+++ b/src/devices/bus/pofo/hpc104.cpp
@@ -100,7 +100,7 @@ pofo_hpc104_device::pofo_hpc104_device(const machine_config &mconfig, device_typ
device_portfolio_expansion_slot_interface(mconfig, *this),
device_nvram_interface(mconfig, *this),
m_ccm(*this, PORTFOLIO_MEMORY_CARD_SLOT_B_TAG),
- m_exp(*this, PORTFOLIO_EXPANSION_SLOT_TAG),
+ m_exp(*this, "exp"),
m_nvram(*this, "nvram", 0x40000, ENDIANNESS_LITTLE),
m_io_sw1(*this, "SW1")
{
@@ -169,7 +169,7 @@ uint8_t pofo_hpc104_device::nrdi_r(offs_t offset, uint8_t data, bool iom, bool b
{
if (offset >= 0x1f000 && offset < 0x5f000)
{
- data = m_nvram[offset - 0x1f000] = data;
+ data = m_nvram[offset - 0x1f000];
}
}
}
diff --git a/src/devices/bus/saitek_osa/expansion.cpp b/src/devices/bus/saitek_osa/expansion.cpp
index bae1dfe0eb5..0c7e6be78bc 100644
--- a/src/devices/bus/saitek_osa/expansion.cpp
+++ b/src/devices/bus/saitek_osa/expansion.cpp
@@ -11,6 +11,10 @@ Used by Saitek(SciSys) chess computers Leonardo, Galileo, Renaissance.
#include "emu.h"
#include "expansion.h"
+#include "maestro.h"
+#include "maestroa.h"
+#include "sparc.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -153,3 +157,15 @@ device_saitekosa_expansion_interface::device_saitekosa_expansion_interface(const
device_saitekosa_expansion_interface::~device_saitekosa_expansion_interface()
{
}
+
+//-------------------------------------------------
+// module list
+//-------------------------------------------------
+
+void saitekosa_expansion_modules(device_slot_interface &device)
+{
+ device.option_add("analyst", OSA_ANALYST);
+ device.option_add("maestro", OSA_MAESTRO);
+ device.option_add("maestroa", OSA_MAESTROA);
+ device.option_add("sparc", OSA_SPARC);
+}
diff --git a/src/devices/bus/saitek_osa/expansion.h b/src/devices/bus/saitek_osa/expansion.h
index 2c245ada301..cb513bf2f4e 100644
--- a/src/devices/bus/saitek_osa/expansion.h
+++ b/src/devices/bus/saitek_osa/expansion.h
@@ -119,10 +119,10 @@ protected:
saitekosa_expansion_device *m_expansion;
};
+void saitekosa_expansion_modules(device_slot_interface &device);
+
+
// device type definition
DECLARE_DEVICE_TYPE(SAITEKOSA_EXPANSION, saitekosa_expansion_device)
-// include here so drivers don't need to
-#include "modules.h"
-
#endif // MAME_BUS_SAITEKOSA_EXPANSION_H
diff --git a/src/devices/bus/saitek_osa/modules.cpp b/src/devices/bus/saitek_osa/modules.cpp
deleted file mode 100644
index 19b7af1ff13..00000000000
--- a/src/devices/bus/saitek_osa/modules.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:hap
-/***************************************************************************
-
- Saitek OSA Expansion Slot modules
-
-***************************************************************************/
-
-#include "emu.h"
-#include "modules.h"
-
-#include "maestro.h"
-#include "maestroa.h"
-#include "sparc.h"
-
-void saitekosa_expansion_modules(device_slot_interface &device)
-{
- device.option_add("analyst", OSA_ANALYST);
- device.option_add("maestro", OSA_MAESTRO);
- device.option_add("maestroa", OSA_MAESTROA);
- device.option_add("sparc", OSA_SPARC);
-}
diff --git a/src/devices/bus/saitek_osa/modules.h b/src/devices/bus/saitek_osa/modules.h
deleted file mode 100644
index 009daf69cec..00000000000
--- a/src/devices/bus/saitek_osa/modules.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:hap
-/***************************************************************************
-
- Saitek OSA Expansion Slot modules
-
-***************************************************************************/
-
-#ifndef MAME_BUS_SAITEKOSA_MODULES_H
-#define MAME_BUS_SAITEKOSA_MODULES_H
-
-#pragma once
-
-void saitekosa_expansion_modules(device_slot_interface &device);
-
-#endif // MAME_BUS_SAITEKOSA_MODULES_H
diff --git a/src/devices/bus/vic10/exp.cpp b/src/devices/bus/vic10/exp.cpp
index a678a2624c3..48f42ad73c1 100644
--- a/src/devices/bus/vic10/exp.cpp
+++ b/src/devices/bus/vic10/exp.cpp
@@ -79,15 +79,6 @@ void vic10_expansion_slot_device::device_start()
m_write_res.resolve_safe();
m_write_cnt.resolve_safe();
m_write_sp.resolve_safe();
-
- // inherit bus clock
- // FIXME: this should be unnecessary as slots pass DERIVED_CLOCK(1, 1) through by default
- if (clock() == 0)
- {
- vic10_expansion_slot_device *root = machine().root_device().subdevice<vic10_expansion_slot_device>(VIC10_EXPANSION_SLOT_TAG);
- assert(root);
- set_unscaled_clock(root->clock());
- }
}
diff --git a/src/devices/bus/vic10/exp.h b/src/devices/bus/vic10/exp.h
index 20d21f99e1c..c2b1f52ec70 100644
--- a/src/devices/bus/vic10/exp.h
+++ b/src/devices/bus/vic10/exp.h
@@ -41,14 +41,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define VIC10_EXPANSION_SLOT_TAG "exp"
-
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/vic20/exp.h b/src/devices/bus/vic20/exp.h
index 96583a29577..dab459cf7bf 100644
--- a/src/devices/bus/vic20/exp.h
+++ b/src/devices/bus/vic20/exp.h
@@ -40,14 +40,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define VIC20_EXPANSION_SLOT_TAG "exp"
-
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/vip/exp.h b/src/devices/bus/vip/exp.h
index bb9cd203690..aa50074e9ca 100644
--- a/src/devices/bus/vip/exp.h
+++ b/src/devices/bus/vip/exp.h
@@ -40,13 +40,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define VIP_EXPANSION_SLOT_TAG "exp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/vme/vme.cpp b/src/devices/bus/vme/vme.cpp
index a6edb30b693..57f0c6170d2 100644
--- a/src/devices/bus/vme/vme.cpp
+++ b/src/devices/bus/vme/vme.cpp
@@ -109,54 +109,34 @@ vme_slot_device::vme_slot_device(const machine_config &mconfig, const char *tag,
vme_slot_device::vme_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_slot_interface(mconfig, *this)
- , m_vme_tag(nullptr)
- , m_vme_slottag(nullptr)
+ , m_vme(*this, finder_base::DUMMY_TAG)
+ , m_slot_nbr(0)
, m_vme_j1_callback(*this)
{
LOG("%s %s\n", tag, FUNCNAME);
}
//-------------------------------------------------
-// update_vme_chains
-//-------------------------------------------------
-void vme_slot_device::update_vme_chains(uint32_t slot_nbr)
-{
- LOG("%s %s - %d\n", FUNCNAME, tag(), slot_nbr);
-}
-
-//-------------------------------------------------
-// set_vme_slot
+// device_start - device-specific startup
//-------------------------------------------------
-void vme_slot_device::set_vme_slot(const char *tag, const char *slottag)
+void vme_slot_device::device_start()
{
- LOG("%s %s - %s\n", FUNCNAME, tag, slottag);
- m_vme_tag = tag;
- m_vme_slottag = slottag;
+ // m_card = dynamic_cast<device_vme_card_interface *>(get_card_device());
}
//-------------------------------------------------
-// device_start - device-specific startup
+// device_resolve_objects - resolve objects that
+// may be needed for other devices to set
+// initial conditions at start time
//-------------------------------------------------
-void vme_slot_device::device_start()
+void vme_slot_device::device_resolve_objects()
{
device_vme_card_interface *dev = dynamic_cast<device_vme_card_interface *>(get_card_device());
- LOG("%s %s - %s:%s\n", tag(), FUNCNAME, m_vme_tag, m_vme_slottag);
+ LOG("%s %s - %s\n", tag(), FUNCNAME, m_vme.finder_tag());
if (dev)
{
- dev->set_vme_tag(m_vme_tag, m_vme_slottag);
+ dev->set_vme_bus(*m_vme, m_slot_nbr);
}
-
- // m_card = dynamic_cast<device_vme_card_interface *>(get_card_device());
-}
-
-//-------------------------------------------------
-// device_config_complete - perform any
-// operations now that the configuration is
-// complete
-//-------------------------------------------------
-void vme_slot_device::device_config_complete()
-{
- LOG("%s %s\n", tag(), FUNCNAME);
}
//-------------------------------------------------
@@ -457,8 +437,6 @@ void vme_device::install_device(vme_amod_t amod, offs_t start, offs_t end, read3
device_vme_card_interface::device_vme_card_interface(const machine_config &mconfig, device_t &device)
: device_interface(device, "vme")
, m_vme(nullptr)
- , m_vme_tag(nullptr)
- , m_vme_slottag(nullptr)
, m_slot(0)
, m_next(nullptr)
{
@@ -471,17 +449,9 @@ device_vme_card_interface::~device_vme_card_interface()
LOG("%s %s\n", m_device->tag(), FUNCNAME);
}
-void device_vme_card_interface::set_vme_tag(const char *tag, const char *slottag)
-{
- LOG("%s %s\n", tag, FUNCNAME);
- m_vme_tag = tag;
- m_vme_slottag = slottag;
-}
-
-void device_vme_card_interface::set_vme_device()
+void device_vme_card_interface::interface_post_start()
{
LOG("%s %s\n", m_device->tag(), FUNCNAME);
- m_vme = device().machine().root_device().subdevice<vme_device>(m_vme_tag);
// printf("*** %s %sfound\n", m_vme_tag, m_vme ? "" : "not ");
if (m_vme) m_vme->add_vme_card(this);
}
diff --git a/src/devices/bus/vme/vme.h b/src/devices/bus/vme/vme.h
index 93947e40e91..e49b23cbbbe 100644
--- a/src/devices/bus/vme/vme.h
+++ b/src/devices/bus/vme/vme.h
@@ -55,12 +55,11 @@
// CONSTANTS
//**************************************************************************
-#define VME_BUS_TAG "vme"
-
//void vme_slot1(device_slot_interface &device); // Disabled until we know how to combine a board driver and a slot device.
void vme_slots(device_slot_interface &device);
class device_vme_card_interface; // This interface is standardized
+class vme_device;
class vme_slot_device : public device_t,
public device_slot_interface
@@ -85,16 +84,15 @@ public:
};
// construction/destruction
- template <typename T>
- vme_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt, uint32_t slot_nbr, char const *bus_tag)
+ template <typename T, typename U>
+ vme_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt, uint32_t slot_nbr, U &&bus_tag)
: vme_slot_device(mconfig, tag, owner, 0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
- set_vme_slot(bus_tag, tag);
- update_vme_chains(slot_nbr);
+ set_vme_slot(std::forward<U>(bus_tag), slot_nbr);
}
vme_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -102,8 +100,7 @@ public:
// Callbacks to the board from the VME bus comes through here
auto vme_j1_callback() { return m_vme_j1_callback.bind(); }
- void set_vme_slot(const char *tag, const char *slottag);
- void update_vme_chains(uint32_t slot_nbr);
+ template <typename T> void set_vme_slot(T &&tag, uint32_t slot_nbr) { m_vme.set_tag(std::forward<T>(tag)); m_slot_nbr = slot_nbr; }
virtual uint8_t read8(offs_t offset);
virtual void write8(offs_t offset, uint8_t data);
@@ -113,10 +110,11 @@ protected:
// device-level overrides
virtual void device_start() override;
- virtual void device_config_complete() override;
+ virtual void device_resolve_objects() override;
// configuration
- const char *m_vme_tag, *m_vme_slottag;
+ required_device<vme_device> m_vme;
+ uint32_t m_slot_nbr;
// callbacks
devcb_write_line m_vme_j1_callback;
@@ -139,8 +137,6 @@ public:
void set_cputag(const char *tag) { m_cputag = tag; }
void use_owner_spaces();
- virtual space_config_vector memory_space_config() const override;
-
const address_space_config m_a32_config;
void add_vme_card(device_vme_card_interface *card);
@@ -196,6 +192,8 @@ protected:
virtual void device_reset() override;
simple_list<device_vme_card_interface> m_device_list;
+ virtual space_config_vector memory_space_config() const override;
+
// internal state
cpu_device *m_maincpu;
@@ -218,22 +216,22 @@ class device_vme_card_interface : public device_interface
template <class ElementType> friend class simple_list;
public:
// inline configuration
- void set_vme_tag(const char *tag, const char *slottag);
+ void set_vme_bus(vme_device &vme, int slot) { m_vme = &vme; m_slot = slot; }
// construction/destruction
virtual ~device_vme_card_interface();
- void set_vme_device();
virtual uint8_t read8(offs_t offset);
virtual void write8(offs_t offset, uint8_t data);
+protected:
device_vme_card_interface(const machine_config &mconfig, device_t &device);
-protected:
+ virtual void interface_post_start() override;
+
device_t *m_device;
vme_device *m_vme;
- const char *m_vme_tag, *m_vme_slottag;
int m_slot;
private:
diff --git a/src/devices/bus/vme/vme_fccpu20.cpp b/src/devices/bus/vme/vme_fccpu20.cpp
index 8759c47d143..ee07b86e1be 100644
--- a/src/devices/bus/vme/vme_fccpu20.cpp
+++ b/src/devices/bus/vme/vme_fccpu20.cpp
@@ -443,8 +443,6 @@ void vme_fccpu20_device::device_start()
{
LOG("%s\n", FUNCNAME);
- set_vme_device();
-
save_pointer (NAME (m_sysrom), sizeof(m_sysrom));
save_pointer (NAME (m_sysram), sizeof(m_sysram));
// save_item(NAME(m_board_id)); // TODO: Save this "non base type" item
diff --git a/src/devices/bus/vme/vme_fcisio.cpp b/src/devices/bus/vme/vme_fcisio.cpp
index d9e35370812..de4c03dfab8 100644
--- a/src/devices/bus/vme/vme_fcisio.cpp
+++ b/src/devices/bus/vme/vme_fcisio.cpp
@@ -405,7 +405,6 @@ vme_fcisio1_card_device::vme_fcisio1_card_device(const machine_config &mconfig,
void vme_fcisio1_card_device::device_start()
{
LOG("%s\n", FUNCNAME);
- set_vme_device();
/* Setup pointer to bootvector in ROM for bootvector handler bootvect_r */
m_sysrom = (uint16_t*)(memregion ("maincpu")->base () + 0xf00000);
diff --git a/src/devices/bus/vme/vme_fcscsi.cpp b/src/devices/bus/vme/vme_fcscsi.cpp
index 508ae910e9c..7324dd907b6 100644
--- a/src/devices/bus/vme/vme_fcscsi.cpp
+++ b/src/devices/bus/vme/vme_fcscsi.cpp
@@ -329,7 +329,6 @@ vme_fcscsi1_card_device::vme_fcscsi1_card_device(const machine_config &mconfig,
void vme_fcscsi1_card_device::device_start()
{
LOG("%s\n", FUNCNAME);
- set_vme_device();
/* Setup pointer to bootvector in ROM for bootvector handler bootvect_r */
m_sysrom = (uint16_t*)(memregion ("maincpu")->base () + 0xe00000);
diff --git a/src/devices/bus/vme/vme_hcpu30.cpp b/src/devices/bus/vme/vme_hcpu30.cpp
index 0c072c20191..2d70c85dd94 100644
--- a/src/devices/bus/vme/vme_hcpu30.cpp
+++ b/src/devices/bus/vme/vme_hcpu30.cpp
@@ -180,8 +180,6 @@ void vme_hcpu30_card_device::device_start()
{
LOG("%s %s\n", tag(), FUNCNAME);
- set_vme_device();
-
save_pointer (NAME (m_sysrom), sizeof(m_sysrom));
save_pointer (NAME (m_sysram), sizeof(m_sysram));
diff --git a/src/devices/bus/vme/vme_mvme350.cpp b/src/devices/bus/vme/vme_mvme350.cpp
index 1b8f2f7a564..a0dca46b996 100644
--- a/src/devices/bus/vme/vme_mvme350.cpp
+++ b/src/devices/bus/vme/vme_mvme350.cpp
@@ -224,7 +224,6 @@ vme_mvme350_card_device::vme_mvme350_card_device(const machine_config &mconfig,
void vme_mvme350_card_device::device_start()
{
LOG("%s %s\n", tag(), FUNCNAME);
- set_vme_device();
/* Setup r/w handlers for shared memory area */
#if 0
diff --git a/src/devices/bus/vme/vme_mzr8300.cpp b/src/devices/bus/vme/vme_mzr8300.cpp
index cdcd3bd267e..99e2e8c0889 100644
--- a/src/devices/bus/vme/vme_mzr8300.cpp
+++ b/src/devices/bus/vme/vme_mzr8300.cpp
@@ -168,7 +168,6 @@ vme_mzr8300_card_device::vme_mzr8300_card_device(const machine_config &mconfig,
void vme_mzr8300_card_device::device_start()
{
LOG("%s %s\n", tag(), FUNCNAME);
- set_vme_device();
/* Setup r/w handlers for first SIO in A16 */
uint32_t base = 0xFF0000;