From efcdeeaed4cf00263f23de8a77b990b4b92893a4 Mon Sep 17 00:00:00 2001 From: Nigel Barnes Date: Mon, 14 Jun 2021 13:13:17 +0100 Subject: [PATCH] bus/coco: Added the Dragon MSX 2+, The Dragon's Claw, Peaksoft Prestel, and CoCo WordPak/WordPak II/WordPak RS/WordPak 2+ devices. --- scripts/src/bus.lua | 10 ++ src/devices/bus/coco/coco_multi.cpp | 123 ++++++++------ src/devices/bus/coco/coco_multi.h | 1 + src/devices/bus/coco/coco_wpk.cpp | 201 +++++++++++++++++++++++ src/devices/bus/coco/coco_wpk.h | 94 +++++++++++ src/devices/bus/coco/coco_wpk2p.cpp | 56 +++++++ src/devices/bus/coco/coco_wpk2p.h | 41 +++++ src/devices/bus/coco/cococart.cpp | 65 ++++++++ src/devices/bus/coco/cococart.h | 3 + src/devices/bus/coco/dragon_claw.cpp | 212 +++++++++++++++++++++++++ src/devices/bus/coco/dragon_claw.h | 59 +++++++ src/devices/bus/coco/dragon_msx2.cpp | 191 ++++++++++++++++++++++ src/devices/bus/coco/dragon_msx2.h | 53 +++++++ src/devices/bus/coco/dragon_serial.cpp | 154 ++++++++++++++++++ src/devices/bus/coco/dragon_serial.h | 52 ++++++ src/mame/drivers/dragon.cpp | 58 ++----- 16 files changed, 1283 insertions(+), 90 deletions(-) create mode 100644 src/devices/bus/coco/coco_wpk.cpp create mode 100644 src/devices/bus/coco/coco_wpk.h create mode 100644 src/devices/bus/coco/coco_wpk2p.cpp create mode 100644 src/devices/bus/coco/coco_wpk2p.h create mode 100644 src/devices/bus/coco/dragon_claw.cpp create mode 100644 src/devices/bus/coco/dragon_claw.h create mode 100644 src/devices/bus/coco/dragon_msx2.cpp create mode 100644 src/devices/bus/coco/dragon_msx2.h create mode 100644 src/devices/bus/coco/dragon_serial.cpp create mode 100644 src/devices/bus/coco/dragon_serial.h 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 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 @@ -485,24 +532,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(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 m_crtc; + required_device m_palette; + required_memory_region m_chargen; + + u16 m_video_addr; + u8 m_video_data; + + std::unique_ptr 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 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 ¢ronics(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 m_via; + required_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 m_ym2413; + required_device m_v9958; + required_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 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 )