summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/src/bus.lua10
-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/mame/drivers/dragon.cpp58
16 files changed, 1283 insertions, 90 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index c50ec0d98bc..c5dd3b198b2 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -3481,16 +3481,26 @@ if (BUSES["COCO"]~=null) then
MAME_DIR .. "src/devices/bus/coco/coco_sym12.h",
MAME_DIR .. "src/devices/bus/coco/coco_t4426.cpp",
MAME_DIR .. "src/devices/bus/coco/coco_t4426.h",
+ MAME_DIR .. "src/devices/bus/coco/coco_wpk.cpp",
+ MAME_DIR .. "src/devices/bus/coco/coco_wpk.h",
+ MAME_DIR .. "src/devices/bus/coco/coco_wpk2p.cpp",
+ MAME_DIR .. "src/devices/bus/coco/coco_wpk2p.h",
MAME_DIR .. "src/devices/bus/coco/cococart.cpp",
MAME_DIR .. "src/devices/bus/coco/cococart.h",
MAME_DIR .. "src/devices/bus/coco/dragon_amtor.cpp",
MAME_DIR .. "src/devices/bus/coco/dragon_amtor.h",
+ MAME_DIR .. "src/devices/bus/coco/dragon_claw.cpp",
+ MAME_DIR .. "src/devices/bus/coco/dragon_claw.h",
MAME_DIR .. "src/devices/bus/coco/dragon_fdc.cpp",
MAME_DIR .. "src/devices/bus/coco/dragon_fdc.h",
MAME_DIR .. "src/devices/bus/coco/dragon_jcbsnd.cpp",
MAME_DIR .. "src/devices/bus/coco/dragon_jcbsnd.h",
MAME_DIR .. "src/devices/bus/coco/dragon_jcbspch.cpp",
MAME_DIR .. "src/devices/bus/coco/dragon_jcbspch.h",
+ MAME_DIR .. "src/devices/bus/coco/dragon_msx2.cpp",
+ MAME_DIR .. "src/devices/bus/coco/dragon_msx2.h",
+ MAME_DIR .. "src/devices/bus/coco/dragon_serial.cpp",
+ MAME_DIR .. "src/devices/bus/coco/dragon_serial.h",
MAME_DIR .. "src/devices/bus/coco/dragon_sprites.cpp",
MAME_DIR .. "src/devices/bus/coco/dragon_sprites.h",
}
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..2d3fc3748d6
--- /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_wpk", "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/mame/drivers/dragon.cpp b/src/mame/drivers/dragon.cpp
index 2b73e06162b..d1a3ae16d40 100644
--- a/src/mame/drivers/dragon.cpp
+++ b/src/mame/drivers/dragon.cpp
@@ -21,23 +21,9 @@
#include "formats/dmk_dsk.h"
#include "formats/sdf_dsk.h"
#include "imagedev/floppy.h"
+#include "bus/coco/cococart.h"
#include "bus/rs232/rs232.h"
-#include "bus/coco/coco_gmc.h"
-#include "bus/coco/coco_orch90.h"
-#include "bus/coco/coco_max.h"
-#include "bus/coco/coco_midi.h"
-#include "bus/coco/coco_pak.h"
-#include "bus/coco/coco_psg.h"
-#include "bus/coco/coco_ram.h"
-#include "bus/coco/coco_ssc.h"
-#include "bus/coco/coco_stecomp.h"
-#include "bus/coco/coco_sym12.h"
-#include "bus/coco/dragon_amtor.h"
-#include "bus/coco/dragon_fdc.h"
-#include "bus/coco/dragon_jcbsnd.h"
-#include "bus/coco/dragon_jcbspch.h"
-#include "bus/coco/dragon_sprites.h"
//**************************************************************************
@@ -153,10 +139,10 @@ static INPUT_PORTS_START( dragon_keyboard )
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_CODE(KEYCODE_X) PORT_CHAR('X')
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z')
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME("UP") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP), '^')
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME("DOWN") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN), 10) PORT_CHAR('[')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME("LEFT") PORT_CODE(KEYCODE_LEFT) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(UCHAR_MAMEKEY(LEFT), 8)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME("RIGHT") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT), 9) PORT_CHAR(']')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME(u8"\u2191") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP), '^')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME(u8"\u2193") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN), 10) PORT_CHAR('[')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME(u8"\u2190") PORT_CODE(KEYCODE_LEFT) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(UCHAR_MAMEKEY(LEFT), 8)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME(u8"\u2192") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT), 9) PORT_CHAR(']')
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
PORT_START("row6")
@@ -171,23 +157,23 @@ static INPUT_PORTS_START( dragon200e_keyboard )
PORT_INCLUDE(dragon_keyboard)
PORT_MODIFY("row0")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME("0 \xC3\x87") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(0xC7)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME(u8"0 \u00c7") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(0xC7)
PORT_MODIFY("row1")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME("\xC3\x91") PORT_CODE(KEYCODE_COLON) PORT_CHAR(0xD1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME(u8"\u00d1") PORT_CODE(KEYCODE_COLON) PORT_CHAR(0xD1)
PORT_MODIFY("row2")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(';') PORT_CHAR('+')
PORT_MODIFY("row5")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME("UP") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP), '^') PORT_CHAR('_')
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME("DOWN \xC2\xA1") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(10) PORT_CHAR(0xA1)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME("RIGHT \xC2\xBF") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(9) PORT_CHAR(0xBF)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME(u8"\u2191") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP), '^') PORT_CHAR('_')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME(u8"\u2193 \u00a1") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(10) PORT_CHAR(0xA1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME(u8"\u2192 \u00bf") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(9) PORT_CHAR(0xBF)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_CHAR(0xA7)
PORT_MODIFY("row6")
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME("CLEAR @") PORT_CODE(KEYCODE_HOME) PORT_CHAR(12) PORT_CHAR('@')
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME("BREAK \xC3\xBC") PORT_CODE(KEYCODE_END) PORT_CODE(KEYCODE_ESC) PORT_CHAR(27) PORT_CHAR(0xFC)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, dragon_state, keyboard_changed, 0) PORT_NAME(u8"BREAK \u00fc") PORT_CODE(KEYCODE_END) PORT_CODE(KEYCODE_ESC) PORT_CHAR(27) PORT_CHAR(0xFC)
INPUT_PORTS_END
static INPUT_PORTS_START( dragon )
@@ -209,23 +195,9 @@ INPUT_PORTS_END
void dragon_cart(device_slot_interface &device)
{
- device.option_add_internal("amtor", DRAGON_AMTOR);
- device.option_add("ccpsg", COCO_PSG);
- device.option_add("dragon_fdc", DRAGON_FDC);
- 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("orch90", COCO_ORCH90);
- device.option_add("pak", COCO_PAK);
- device.option_add("premier_fdc", PREMIER_FDC);
- device.option_add("ram", COCO_PAK_RAM);
- device.option_add("sdtandy_fdc", SDTANDY_FDC);
- 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);
+ dragon_cart_add_basic_devices(device);
+ dragon_cart_add_fdcs(device);
+ dragon_cart_add_multi_pak(device);
}
void dragon_alpha_state::dragon_formats(format_registration &fr)
@@ -553,7 +525,7 @@ ROM_END
#define rom_dragon64h rom_dragon64
#define rom_tanodr64h rom_tanodr64
-// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
COMP( 1982, dragon32, 0, 0, dragon32, dragon, dragon_state, empty_init, "Dragon Data Ltd", "Dragon 32", 0 )
COMP( 1983, dragon64, dragon32, 0, dragon64, dragon, dragon64_state, empty_init, "Dragon Data Ltd", "Dragon 64", 0 )
COMP( 19??, dragon64h, dragon32, 0, dragon64h, dragon, dragon64_state, empty_init, "Dragon Data Ltd", "Dragon 64 (HD6309E CPU)", MACHINE_UNOFFICIAL )