diff options
Diffstat (limited to 'src/devices/bus/msx/cart/disk.cpp')
-rw-r--r-- | src/devices/bus/msx/cart/disk.cpp | 1405 |
1 files changed, 1405 insertions, 0 deletions
diff --git a/src/devices/bus/msx/cart/disk.cpp b/src/devices/bus/msx/cart/disk.cpp new file mode 100644 index 00000000000..50cdbc3b74d --- /dev/null +++ b/src/devices/bus/msx/cart/disk.cpp @@ -0,0 +1,1405 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol +/***************************************************************************** + * + * MSX Floopy drive interface add-on cartridges + * + * Currently supported: + * - AVT DPF-550 + DD 5.25" Drive - FD1770 or FD179x? + * - Digital Design Drive DDX + DD 5.25" Drive - WD2793 + * - Microsol CDX-2 + DD 5.25" Drive - WD2793? + * - Mitsubishi ML-30DC + ML-30FD DSDD 3.5" Drive - WD2793 + * - National FS-CF351 + FS-FD351 DSDD 3.5" Drive - MB8877A + * - Panasonic FS-FD1 + DSDD 3.5" Drive - WD2793? + * - Panasonic FS-FD1A with DSDD 3.5" Drive - TC8566F + * - Rom label reads: "FDC BIOS V1.0 / COPYRIGHT MEI / 1987 DASFD1AA1" + * - Philips NMS-1200 - Floppy interface - WD2793? + * - Philips VY-0010 (Interface cartridge + 1 3.5" SS floppy drive) + * - Sanyo MFD-001 + DS 5.25" Drive - MB8877? + * - Sharp Epcom HB-3600 + HB-6000 DD 5.25" Drive - WD2793 + * - Sony HBD-20W + DSDD 3.5" Drive - WD2793 + * - Sony HBD-50 + SSDD 3.5" Drive - WD2793 + * - Missing version SNYJX130 + * - Sony HBD-F1 + DSDD 3.5" Drive - WD2793 + * - Talent DPF-550 + SS 5.25" Drive - WD1770 + * - Toshiba HX-F101PE + SS 3.5" Drive - WD2793 + * - Yamaha FD-03 + SSDD 3.5" Floppy drive - FD1793 (according to service manual) + * - Yamaha FD-051 + FD-05 DSDD 3.5" Drive - WD2793 + * - Loading seems slower than other units + * + * Not supported yet: + * - Canon VF-100 - DSDD 3.5" Floppy drive + interface + 1 floppy disk containing MSX-DOS + * - Talent DPF-555 - WD1772 - DSDD 5.25" Floppy drive (360KB) plus interface (manufactured by Daewoo) + * - Rom label markings: MSX DISK / DPF 555D + * + * Drive only: + * - Philps VY-0011 - 3.5" SSDD Floppy drive + * - Talent DPF-560 - DSDD 5.25" Floppy drive + * + * To be investigated: + * - Daewoo CPF-350C - DD 3.5" Floppy drive + * - Daewoo CPF-360C - DD 3.5" Floppy drive + * - Daewoo MPF-550 - DSDD 5.25" Floppy drive + interface + * = Daewoo MPF-560 - DSDD 5.25" Floppy drive + * - DMX Interface para drive - Interface + 1 floppy disk containg MSX-DOS 1.0 + * - Fenner FD-300 - DSDD 3.5" Floppy drive + * - Fenner FD-400 - Floppy interface for FD-300 + * - Hitachi MPF-310CH - DSDD Floppy drive + * - hitachi MPC-310CH - Interface for MPF-310CH + * - JVC HC-F303 - Floppy drive + * - Philips NMS-9111 - 3.5" Floppy drive + * - Philips NMS-9113 - 3.5" Floppy drive + * - Sakir AFD-01 - SSDD 3.5" Floppy drive + * - Sanyo MFD-002 - 360KB 5.25" Floppy drive (2nd drive for MFD-001?) + * - Sanyo MFD-25FD - DSDD 3.5" Floppy drive + * - Sanyo MFD-35 - SSDD 3.5" Floppy drive + interface + * - Sony HBD-100 - SSDD 3.5" Floppy drive + * - Sony HBD-30X/30W - DSDD 3.5" drive + * - Sony HBX-30 (interface only, meant for 30W) - WD2793 + * - Spectravideo SVI-213 - MB8877A - Floppy interface for SVI-707 + * - Spectravideo SVI-707 - MB8877A - 5.25" SSDD? drive (320KB) - There seem to be 2 ROMs on the PCB, apparently one is for MSX and one is for CP/M operation? + * - See https://plus.google.com/photos/115644813183575095400/albums/5223347091895442113?banner=pwa + * - Spectravideo SVI-717 - Interface for 2 drives? + * - Spectravideo SVI-787 - SSDD 3.5" Floppy drive + * - Spectravideo SVI-801 - Interface + * - Toshiba HX-F100 - Interface + SSDD 3.5" Floppy drive + * - Toshiba HX-F101 - Interface + SSDD or DSDD 3.5" Floppy drive + * - Yamaha FD-01 - Interface + SSDD 3.5" Floppy drive + * - Other models: + * - ACVS 3.5" Floppy drive interface + * - Tradeco floppy interface + * - Angeisa 3.5" Floppy drive + * - Angeisa 5.25" 360KB Floppy drive + * - Angeisa 5.25" 720KB Floppy drive + * - Angeisa floppy drive interface + * - Datagame floppy drive interface + * - Digital Design DSDD 3.5" Floppy drive + * - Digital Design 5.25" 360KB Floppy drive + * - Digital Design 5.25" 720KB Floppy drive + * - Digital Design floppy drive interface + * - DMX 3.5" Floppy drive + * - DMX floppy drive interface + * - Liftron 3.5" Floppy drive + * - Liftron floppy drive interface + * - Microsol DRX-180 5.25" Floppy drive FS + * - Microsol DRX-360 5.25" Floppy drive FD + * - Microsol DRX-720 5.25" Floppy drive 80 track (720KB) + * - Microsol CDX-1 floppy interface + * - Racidata 3.5" Floppy drive + * - Racidata 5.25" Floppy drive + * - Racidata floppy interface + * - Sileman Triton-s 3.5" FS Floppy drive + * - Sileman Triton-d 3.5" FD Floppy drive + * - Talent TPF-723 5.25" Floppy drive + * - Talent TPF-725 5.25" Flpppy drive + * - Technohead Leopard 3.5" Floppy drive + * - Technohead Leopard 5.25" Floppy drive + * - Technohead floppy interface + * - More?? + * + * Several model references found in Vitropedia (ISBN 9781409212774) + * + ****************************************************************************/ + +#include "emu.h" +#include "disk.h" +#include "slotoptions.h" + +#include "bus/msx/slot/cartridge.h" +#include "imagedev/floppy.h" +#include "machine/wd_fdc.h" +#include "machine/upd765.h" + +#include "softlist_dev.h" + +#include "formats/dmk_dsk.h" +#include "formats/msx_dsk.h" + + +DECLARE_DEVICE_TYPE(MSX_CART_AVDPF550, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_CDX2, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_DDX3, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_FD03, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_FD051, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_FSCF351, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_FSFD1, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_FSFD1A, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_HB3600, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_HBD20W, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_HBD50, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_HBDF1, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_HXF101PE, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_MFD001, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_ML30DC, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_NMS1200, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_TADPF550, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_VY0010, msx_cart_interface) + + +void msx_cart_disk_register_options(device_slot_interface &device) +{ + using namespace bus::msx::cart; + device.option_add_internal(slotoptions::DISK_AVDPF550, MSX_CART_AVDPF550); + device.option_add_internal(slotoptions::DISK_CDX2, MSX_CART_CDX2); + device.option_add_internal(slotoptions::DISK_DDX3, MSX_CART_DDX3); + device.option_add_internal(slotoptions::DISK_FD03, MSX_CART_FD03); + device.option_add_internal(slotoptions::DISK_FD051, MSX_CART_FD051); + device.option_add_internal(slotoptions::DISK_FSCF351, MSX_CART_FSCF351); + device.option_add_internal(slotoptions::DISK_FSFD1, MSX_CART_FSFD1); + device.option_add_internal(slotoptions::DISK_FSFD1A, MSX_CART_FSFD1A); + device.option_add_internal(slotoptions::DISK_HB3600, MSX_CART_HB3600); + device.option_add_internal(slotoptions::DISK_HBD20W, MSX_CART_HBD20W); + device.option_add_internal(slotoptions::DISK_HBD50, MSX_CART_HBD50); + device.option_add_internal(slotoptions::DISK_HBDF1, MSX_CART_HBDF1); + device.option_add_internal(slotoptions::DISK_HXF101PE, MSX_CART_HXF101PE); + device.option_add_internal(slotoptions::DISK_MFD001, MSX_CART_MFD001); + device.option_add_internal(slotoptions::DISK_ML30DC, MSX_CART_ML30DC); + device.option_add_internal(slotoptions::DISK_NMS1200, MSX_CART_NMS1200); + device.option_add_internal(slotoptions::DISK_TADPF550, MSX_CART_TADPF550); + device.option_add_internal(slotoptions::DISK_VY0010, MSX_CART_VY0010); +} + + +namespace { + +void msx_floppies(device_slot_interface &device) +{ + device.option_add("35dd", FLOPPY_35_DD); + device.option_add("35ssdd", FLOPPY_35_SSDD); + device.option_add("525dd", FLOPPY_525_DD); + device.option_add("525ssdd", FLOPPY_525_SSDD); +} + + + +class msx_cart_disk_device : public device_t, public msx_cart_interface +{ +public: + virtual std::error_condition initialize_cartridge(std::string &message) override; + +protected: + msx_cart_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int fdc_regs_start_page, int fdc_regs_end_page) + : device_t(mconfig, type, tag, owner, clock) + , msx_cart_interface(mconfig, *this) + , m_floppy0(*this, "fdc:0") + , m_floppy1(*this, "fdc:1") + , m_floppy(nullptr) + , m_fdc_regs_start_page(fdc_regs_start_page) + , m_fdc_regs_end_page(fdc_regs_end_page) + { } + + static void floppy_formats(format_registration &fr); + void softlist_35(machine_config &config); + void softlist_525(machine_config &config); + template <bool Is35, bool IsDS> void add_floppy_mconfig(machine_config &config); + + static constexpr int PAGE0 = 0; + static constexpr int PAGE1 = 1; + static constexpr int PAGE2 = 2; + static constexpr int PAGE3 = 3; + static constexpr bool F35 = true; + static constexpr bool F525 = false; + static constexpr bool DS = true; + static constexpr bool SS = false; + static constexpr bool FORCE_READY = true; + + required_device<floppy_connector> m_floppy0; + optional_device<floppy_connector> m_floppy1; + floppy_image_device *m_floppy; + int m_fdc_regs_start_page; + int m_fdc_regs_end_page; +}; + +void msx_cart_disk_device::floppy_formats(format_registration &fr) +{ + fr.add_mfm_containers(); + fr.add(FLOPPY_MSX_FORMAT); + fr.add(FLOPPY_DMK_FORMAT); +} + +std::error_condition msx_cart_disk_device::initialize_cartridge(std::string &message) +{ + if (!cart_rom_region()) + { + message = "msx_cart_disk_device: Required region 'rom' was not found."; + return image_error::INTERNAL; + } + + if (cart_rom_region()->bytes() != 0x4000) + { + message = "msx_cart_disk_device: Region 'rom' has unsupported size."; + return image_error::INVALIDLENGTH; + } + + return std::error_condition(); +} + +void msx_cart_disk_device::softlist_35(machine_config &config) +{ + // Attach software lists + // We do not know in what kind of machine the user has inserted the floppy interface + // so we list all msx floppy software lists. + // + SOFTWARE_LIST(config, "msx2_flop_list").set_original("msx2_flop"); + SOFTWARE_LIST(config, "msx1_flop_list").set_compatible("msx1_flop"); +} + +void msx_cart_disk_device::softlist_525(machine_config &config) +{ + // Attach software lists + SOFTWARE_LIST(config, "msx1_flop_525_list").set_compatible("msx1_flop_525"); +} + +template <bool Is35, bool IsDS> +void msx_cart_disk_device::add_floppy_mconfig(machine_config &config) +{ + FLOPPY_CONNECTOR(config, "fdc:0", msx_floppies, Is35 ? (IsDS ? "35dd" : "35ssdd") : (IsDS ? "525dd" : "525ssdd"), msx_cart_disk_device::floppy_formats).enable_sound(true); + if (Is35) + softlist_35(config); + else + softlist_525(config); +} + + + + +class disk_tc8566_device : public msx_cart_disk_device +{ +protected: + disk_tc8566_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) + : msx_cart_disk_device(mconfig, type, tag, owner, clock, PAGE1, PAGE2) + , m_fdc(*this, "fdc") + { } + + required_device<tc8566af_device> m_fdc; +}; + + + +class disk_wd_device : public msx_cart_disk_device +{ +protected: + disk_wd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int fdc_regs_start_page = PAGE1, int fdc_regs_end_page = PAGE2) + : msx_cart_disk_device(mconfig, type, tag, owner, clock, fdc_regs_start_page, fdc_regs_end_page) + , m_fdc(*this, "fdc") + { } + + required_device<wd_fdc_device_base> m_fdc; + + virtual void device_reset() override + { + m_fdc->dden_w(false); + } + + template <bool Is35, bool IsDS, typename FDCType> void add_mconfig(machine_config &config, FDCType &&type) + { + add_mconfig<Is35, IsDS, false>(config, type); + } + + template <bool Is35, bool IsDS, bool ForceReady, typename FDCType> void add_mconfig(machine_config &config, FDCType &&type) + { + std::forward<FDCType>(type)(config, m_fdc, 4_MHz_XTAL / 4); + if (ForceReady) + m_fdc->set_force_ready(true); + add_floppy_mconfig<Is35, IsDS>(config); + } +}; + + + +class disk_type1_device : public disk_wd_device +{ +public: + virtual std::error_condition initialize_cartridge(std::string &message) override; + +protected: + disk_type1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int fdc_regs_start_page = PAGE1, int fdc_regs_end_page = PAGE2) + : disk_wd_device(mconfig, type, tag, owner, clock, fdc_regs_start_page, fdc_regs_end_page) + , m_led(*this, "led0") + , m_side_control(0) + , m_control(0) + { } + + // device_t implementation + virtual void device_start() override ATTR_COLD; + virtual void device_post_load() override; + + u8 side_control_r(); + u8 control_r(); + u8 status_r(); + void set_side_control(u8 data); + void set_control(u8 data); + + output_finder<> m_led; + u8 m_side_control; + u8 m_control; +}; + +void disk_type1_device::device_start() +{ + m_led.resolve(); + + save_item(NAME(m_side_control)); + save_item(NAME(m_control)); +} + +std::error_condition disk_type1_device::initialize_cartridge(std::string &message) +{ + std::error_condition result = disk_wd_device::initialize_cartridge(message); + if (result) + return result; + + page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base()); + for (int i = m_fdc_regs_start_page; i <= m_fdc_regs_end_page; i++) + { + const offs_t base = 0x4000 * i; + page(i)->install_read_handler(base + 0x3ff8, base + 0x3ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r))); + page(i)->install_read_handler(base + 0x3ff9, base + 0x3ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r))); + page(i)->install_read_handler(base + 0x3ffa, base + 0x3ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r))); + page(i)->install_read_handler(base + 0x3ffb, base + 0x3ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r))); + page(i)->install_read_handler(base + 0x3ffc, base + 0x3ffc, emu::rw_delegate(*this, FUNC(disk_type1_device::side_control_r))); + page(i)->install_read_handler(base + 0x3ffd, base + 0x3ffd, emu::rw_delegate(*this, FUNC(disk_type1_device::control_r))); + page(i)->install_read_handler(base + 0x3fff, base + 0x3fff, emu::rw_delegate(*this, FUNC(disk_type1_device::status_r))); + page(i)->install_write_handler(base + 0x3ff8, base + 0x3ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w))); + page(i)->install_write_handler(base + 0x3ff9, base + 0x3ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w))); + page(i)->install_write_handler(base + 0x3ffa, base + 0x3ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w))); + page(i)->install_write_handler(base + 0x3ffb, base + 0x3ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w))); + page(i)->install_write_handler(base + 0x3ffc, base + 0x3ffc, emu::rw_delegate(*this, FUNC(disk_type1_device::set_side_control))); + page(i)->install_write_handler(base + 0x3ffd, base + 0x3ffd, emu::rw_delegate(*this, FUNC(disk_type1_device::set_control))); + } + + return std::error_condition(); +} + +void disk_type1_device::device_post_load() +{ + set_control(m_control); +} + +void disk_type1_device::set_control(u8 data) +{ + u8 old_m_control = m_control; + + m_control = data; + + switch (m_control & 0x03) + { + case 0: + case 2: + m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr; + break; + + case 1: + m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr; + break; + + default: + m_floppy = nullptr; + break; + } + + if (m_floppy) + { + m_floppy->mon_w((m_control & 0x80) ? 0 : 1); + m_floppy->ss_w(m_side_control & 0x01); + } + + m_fdc->set_floppy(m_floppy); + + if ((old_m_control ^ m_control) & 0x40) + { + m_led = BIT(~m_control, 6); + } +} + +void disk_type1_device::set_side_control(u8 data) +{ + m_side_control = data; + + if (m_floppy) + { + m_floppy->ss_w(m_side_control & 0x01); + } +} + +u8 disk_type1_device::side_control_r() +{ + return 0xfe | (m_side_control & 0x01); +} + +u8 disk_type1_device::control_r() +{ + return (m_control & 0x83) | 0x78; +} + +u8 disk_type1_device::status_r() +{ + return 0x3f | (m_fdc->intrq_r() ? 0 : 0x40) | (m_fdc->drq_r() ? 0 : 0x80); +} + + + +class fd051_device : public disk_type1_device +{ +public: + fd051_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_type1_device(mconfig, MSX_CART_FD051, tag, owner, clock, PAGE0, PAGE3) + { } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + add_mconfig<F35, DS, FORCE_READY>(config, WD2793); + } +}; + + + +class fsfd1_device : public disk_type1_device +{ +public: + fsfd1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_type1_device(mconfig, MSX_CART_FSFD1, tag, owner, clock) + { } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + add_mconfig<F35, DS>(config, WD2793); + } +}; + + + +class hb3600_device : public disk_type1_device +{ +public: + hb3600_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_type1_device(mconfig, MSX_CART_HB3600, tag, owner, clock) + { } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + add_mconfig<F525, DS, FORCE_READY>(config, WD2793); + } +}; + + + +class hbd20w_device : public disk_type1_device +{ +public: + hbd20w_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_type1_device(mconfig, MSX_CART_HBD20W, tag, owner, clock) + { } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + add_mconfig<F35, DS>(config, WD2793); + } +}; + + + +class hbd50_device : public disk_type1_device +{ +public: + hbd50_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_type1_device(mconfig, MSX_CART_HBD50, tag, owner, clock, PAGE0, PAGE3) + { } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + add_mconfig<F35, SS>(config, WD2793); + } +}; + + + +class hbdf1_device : public disk_type1_device +{ +public: + hbdf1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_type1_device(mconfig, MSX_CART_HBDF1, tag, owner, clock) + { } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + add_mconfig<F35, DS>(config, WD2793); + } +}; + + + +class ml30dc_device : public disk_type1_device +{ +public: + ml30dc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_type1_device(mconfig, MSX_CART_ML30DC, tag, owner, clock) + { } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + add_mconfig<F35, DS, FORCE_READY>(config, WD2793); + // Optional second drive in the same enclosure + //FLOPPY_CONNECTOR(config, "fdc:1", msx_floppies, "35dd", msx_cart_disk_device::floppy_formats); + } +}; + + + +class nms1200_device : public disk_type1_device +{ +public: + nms1200_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_type1_device(mconfig, MSX_CART_NMS1200, tag, owner, clock) + { } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + add_mconfig<F35, DS, FORCE_READY>(config, WD2793); + } +}; + + + +class vy0010_device : public disk_type1_device +{ +public: + vy0010_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_type1_device(mconfig, MSX_CART_VY0010, tag, owner, clock) + { } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + add_mconfig<F35, SS, FORCE_READY>(config, WD2793); + } +}; + + + +class disk_type2_device : public disk_wd_device +{ +public: + virtual std::error_condition initialize_cartridge(std::string &message) override; + +protected: + disk_type2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int fdc_regs_start_page = PAGE1, int fdc_regs_end_page = PAGE2) + : disk_wd_device(mconfig, type, tag, owner, clock, fdc_regs_start_page, fdc_regs_end_page) + , m_led(*this, "led0") + , m_control(0) + { } + + // device_t implementation + virtual void device_start() override ATTR_COLD; + virtual void device_post_load() override; + + void set_control(u8 data); + u8 status_r(); + + output_finder<> m_led; + u8 m_control; +}; + +void disk_type2_device::device_start() +{ + m_led.resolve(); + + save_item(NAME(m_control)); +} + +void disk_type2_device::device_post_load() +{ + set_control(m_control); +} + +std::error_condition disk_type2_device::initialize_cartridge(std::string &message) +{ + std::error_condition result = disk_wd_device::initialize_cartridge(message); + if (result) + return result; + + page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base()); + for (int i = m_fdc_regs_start_page; i <= m_fdc_regs_end_page; i++) + { + const offs_t base = 0x4000 * i; + page(i)->install_read_handler(base + 0x3fb8, base + 0x3fb8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r))); + page(i)->install_read_handler(base + 0x3fb9, base + 0x3fb9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r))); + page(i)->install_read_handler(base + 0x3fba, base + 0x3fba, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r))); + page(i)->install_read_handler(base + 0x3fbb, base + 0x3fbb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r))); + page(i)->install_read_handler(base + 0x3fbc, base + 0x3fbc, emu::rw_delegate(*this, FUNC(disk_type2_device::status_r))); + page(i)->install_write_handler(base + 0x3fb8, base + 0x3fb8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w))); + page(i)->install_write_handler(base + 0x3fb9, base + 0x3fb9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w))); + page(i)->install_write_handler(base + 0x3fba, base + 0x3fba, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w))); + page(i)->install_write_handler(base + 0x3fbb, base + 0x3fbb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w))); + page(i)->install_write_handler(base + 0x3fbc, base + 0x3fbc, emu::rw_delegate(*this, FUNC(disk_type2_device::set_control))); + } + + return std::error_condition(); +} + +void disk_type2_device::set_control(u8 data) +{ + uint8_t old_m_control = m_control; + + m_control = data; + + switch (m_control & 3) + { + case 1: + m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr; + break; + + case 2: + m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr; + break; + + default: + m_floppy = nullptr; + break; + } + + if (m_floppy) + { + m_floppy->mon_w((m_control & 0x08) ? 0 : 1); + m_floppy->ss_w((m_control & 0x04) ? 1 : 0); + } + + m_fdc->set_floppy(m_floppy); + + if ((old_m_control ^ m_control) & 0x40) + { + m_led = BIT(~m_control, 6); + } +} + +u8 disk_type2_device::status_r() +{ + return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0); +} + + + +class fscf351_device : public disk_type2_device +{ +public: + fscf351_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_type2_device(mconfig, MSX_CART_FSCF351, tag, owner, clock) + { } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + add_mconfig<F35, DS, FORCE_READY>(config, MB8877); + } +}; + + + +class tadpf550_device : public disk_type2_device +{ +public: + tadpf550_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_type2_device(mconfig, MSX_CART_TADPF550, tag, owner, clock) + { } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + WD1770(config, m_fdc, 8_MHz_XTAL); + add_floppy_mconfig<F525, SS>(config); + } +}; + + + +class disk_type5_device : public disk_wd_device +{ +public: + virtual std::error_condition initialize_cartridge(std::string &message) override; + +protected: + disk_type5_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) + : disk_wd_device(mconfig, type, tag, owner, clock) + , m_control(0) + { } + + // device_t implementation + virtual void device_start() override ATTR_COLD; + virtual void device_post_load() override; + + void control_w(u8 control); + virtual u8 status_r(); + + u8 m_control; +}; + +void disk_type5_device::device_start() +{ + save_item(NAME(m_control)); +} + +std::error_condition disk_type5_device::initialize_cartridge(std::string &message) +{ + std::error_condition result = disk_wd_device::initialize_cartridge(message); + if (result) + return result; + + page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base()); + + // Install IO read/write handlers + io_space().install_write_handler(0xd0, 0xd0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w))); + io_space().install_write_handler(0xd1, 0xd1, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w))); + io_space().install_write_handler(0xd2, 0xd2, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w))); + io_space().install_write_handler(0xd3, 0xd3, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w))); + io_space().install_write_handler(0xd4, 0xd4, emu::rw_delegate(*this, FUNC(disk_type5_device::control_w))); + io_space().install_read_handler(0xd0, 0xd0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r))); + io_space().install_read_handler(0xd1, 0xd1, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r))); + io_space().install_read_handler(0xd2, 0xd2, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r))); + io_space().install_read_handler(0xd3, 0xd3, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r))); + io_space().install_read_handler(0xd4, 0xd4, emu::rw_delegate(*this, FUNC(disk_type5_device::status_r))); + + return std::error_condition(); +} + +void disk_type5_device::device_post_load() +{ + control_w(m_control); +} + +void disk_type5_device::control_w(u8 control) +{ + m_control = control; + + switch (m_control & 0x0f) + { + case 0x01: + m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr; + break; + + case 0x02: + m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr; + break; + + default: + m_floppy = nullptr; + break; + } + + if (m_floppy) + { + m_floppy->mon_w(BIT(m_control, 5) ? 0 : 1); + m_floppy->ss_w(BIT(m_control, 4) ? 1 : 0); + } + + m_fdc->set_floppy(m_floppy); +} + +u8 disk_type5_device::status_r() +{ + return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0); +} + + +class cdx2_device : public disk_type5_device +{ +public: + cdx2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_type5_device(mconfig, MSX_CART_CDX2, tag, owner, clock) + { } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + add_mconfig<F525, DS>(config, WD2793); + } +}; + + +class ddx3_device : public disk_type5_device +{ +public: + ddx3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_type5_device(mconfig, MSX_CART_DDX3, tag, owner, clock) + { } + +protected: + virtual void device_add_mconfig(machine_config &config) override + { + add_mconfig<F525, DS, FORCE_READY>(config, WD2793); + } +}; + + + +class fsfd1a_device : public disk_tc8566_device +{ +public: + fsfd1a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_tc8566_device(mconfig, MSX_CART_FSFD1A, tag, owner, clock) + { } + + virtual std::error_condition initialize_cartridge(std::string &message) override; + +protected: + // device_t implementation + virtual void device_start() override { } + virtual void device_add_mconfig(machine_config &config) override + { + TC8566AF(config, m_fdc, 16'000'000); + add_floppy_mconfig<F35, DS>(config); + } +}; + +std::error_condition fsfd1a_device::initialize_cartridge(std::string &message) +{ + std::error_condition result = disk_tc8566_device::initialize_cartridge(message); + if (result) + return result; + + page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base()); + for (int i = m_fdc_regs_start_page; i <= m_fdc_regs_end_page; i++) + { + const offs_t base = 0x4000 * i; + page(i)->install_read_handler(base + 0x3ffa, base + 0x3ffa, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::msr_r))); + page(i)->install_read_handler(base + 0x3ffb, base + 0x3ffb, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::fifo_r))); + page(i)->install_write_handler(base + 0x3ff8, base + 0x3ff8, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::dor_w))); + page(i)->install_write_handler(base + 0x3ff9, base + 0x3ff9, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::cr1_w))); + page(i)->install_write_handler(base + 0x3ffb, base + 0x3ffb, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::fifo_w))); + } + + return std::error_condition(); +} + + + +class fd03_device : public disk_wd_device +{ +public: + fd03_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_wd_device(mconfig, MSX_CART_FD03, tag, owner, clock) + , m_led(*this, "led0") + , m_control(0) + { } + + virtual std::error_condition initialize_cartridge(std::string &message) override; + +protected: + // device_t implementation + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + virtual void device_post_load() override; + + u8 status_r(); + u8 dskchg_r(); + void set_control(u8 data); + void dskchg_w(u8 data); + + output_finder<> m_led; + u8 m_control; +}; + +void fd03_device::device_add_mconfig(machine_config &config) +{ + add_mconfig<F35, SS>(config, FD1793); +} + +void fd03_device::device_start() +{ + m_led.resolve(); + + save_item(NAME(m_control)); +} + +std::error_condition fd03_device::initialize_cartridge(std::string &message) +{ + if (!cart_rom_region()) + { + message = "fd03_device:: Required region 'rom' was not found."; + return image_error::INTERNAL; + } + + if (cart_rom_region()->bytes() != 0x4000 && cart_rom_region()->bytes() != 0x8000) + { + message = "fd03_device: Region 'rom' has unsupported size."; + return image_error::INVALIDLENGTH; + } + + page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base()); + if (cart_rom_region()->bytes() >= 0x8000) + page(2)->install_rom(0x8000,0xbfff, cart_rom_region()->base() + 0x4000); + + for (int i = m_fdc_regs_start_page; i <= m_fdc_regs_end_page; i++) + { + const offs_t base = 0x4000 * i; + page(i)->install_read_handler(base + 0x3fc0, base + 0x3fc0, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r))); + page(i)->install_read_handler(base + 0x3fc1, base + 0x3fc1, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r))); + page(i)->install_read_handler(base + 0x3fc2, base + 0x3fc2, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r))); + page(i)->install_read_handler(base + 0x3fc3, base + 0x3fc3, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r))); + page(i)->install_read_handler(base + 0x3fe0, base + 0x3fef, emu::rw_delegate(*this, FUNC(fd03_device::status_r))); + page(i)->install_read_handler(base + 0x3ff0, base + 0x3fff, emu::rw_delegate(*this, FUNC(fd03_device::dskchg_r))); + page(i)->install_write_handler(base + 0x3fc0, base + 0x3fc0, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w))); + page(i)->install_write_handler(base + 0x3fc1, base + 0x3fc1, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w))); + page(i)->install_write_handler(base + 0x3fc2, base + 0x3fc2, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w))); + page(i)->install_write_handler(base + 0x3fc3, base + 0x3fc3, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w))); + page(i)->install_write_handler(base + 0x3fe0, base + 0x3fef, emu::rw_delegate(*this, FUNC(fd03_device::set_control))); + page(i)->install_write_handler(base + 0x3ff0, base + 0x3fff, emu::rw_delegate(*this, FUNC(fd03_device::dskchg_w))); + } + + return std::error_condition(); +} + +void fd03_device::device_post_load() +{ + set_control(m_control); +} + +void fd03_device::set_control(u8 data) +{ + u8 old_m_control = m_control; + + m_control = data; + + switch (m_control & 0x03) + { + case 1: + m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr; + break; + + case 2: + m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr; + break; + + default: + m_floppy = nullptr; + break; + } + + if (m_floppy) + { + m_floppy->mon_w(BIT(m_control, 2) ? 0 : 1); + } + + m_fdc->set_floppy(m_floppy); + + if ((old_m_control ^ m_control) & 0x40) + { + m_led = BIT(~m_control, 6); + } +} + +u8 fd03_device::status_r() +{ + // bit 0 - drive 0 ready / has media + // bit 1 - drive 1 ready / has media + // bit 2 - diskchange drive 0 + // bit 3 - diskchange drive 1 + u8 result = 0x30; + if (!m_floppy0) + result |= 0x01; + if (!m_floppy1) + result |= 0x02; + if (m_floppy0 && m_floppy0->get_device()->dskchg_r()) + result |= 0x04; + if (m_floppy1 && m_floppy1->get_device()->dskchg_r()) + result |= 0x08; + + return result | (m_fdc->intrq_r() ? 0x80 : 0) | (m_fdc->drq_r() ? 0x40 : 0); +} + +u8 fd03_device::dskchg_r() +{ + if (m_floppy1) + m_floppy1->get_device()->dskchg_w(0); + + return 0xff; +} + +void fd03_device::dskchg_w(u8 data) +{ + if (m_floppy0) + m_floppy0->get_device()->dskchg_w(0); +} + + + +class hxf101pe_device : public disk_wd_device +{ +public: + hxf101pe_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_wd_device(mconfig, MSX_CART_HXF101PE, tag, owner, clock, PAGE1, PAGE1) + , m_side_motor(0) + , m_drive_select0(0) + , m_drive_select1(0) + { } + + virtual std::error_condition initialize_cartridge(std::string &message) override; + +protected: + // device_t implementation + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + virtual void device_post_load() override; + + void set_side_motor(); + void select_drive(); + u8 side_motor_r(); + u8 select0_r(); + u8 select1_r(); + u8 status_r(); + void side_motor_w(u8 data); + void select0_w(u8 data); + void select1_w(u8 data); + + u8 m_side_motor; + u8 m_drive_select0; + u8 m_drive_select1; +}; + +void hxf101pe_device::device_add_mconfig(machine_config &config) +{ + add_mconfig<F35, SS>(config, WD2793); +} + +void hxf101pe_device::device_start() +{ + save_item(NAME(m_side_motor)); + save_item(NAME(m_drive_select0)); + save_item(NAME(m_drive_select1)); +} + +std::error_condition hxf101pe_device::initialize_cartridge(std::string &message) +{ + std::error_condition result = disk_wd_device::initialize_cartridge(message); + if (result) + return result; + + page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base()); + page(1)->install_read_handler(0x7ff0, 0x7ff0, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r))); + page(1)->install_read_handler(0x7ff1, 0x7ff1, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r))); + page(1)->install_read_handler(0x7ff2, 0x7ff2, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r))); + page(1)->install_read_handler(0x7ff3, 0x7ff3, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r))); + page(1)->install_read_handler(0x7ff4, 0x7ff4, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::side_motor_r))); + page(1)->install_read_handler(0x7ff5, 0x7ff5, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::select0_r))); + page(1)->install_read_handler(0x7ff6, 0x7ff6, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::select1_r))); + page(1)->install_read_handler(0x7ff7, 0x7ff7, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::status_r))); + page(1)->install_write_handler(0x7ff0, 0x7ff0, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w))); + page(1)->install_write_handler(0x7ff1, 0x7ff1, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w))); + page(1)->install_write_handler(0x7ff2, 0x7ff2, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w))); + page(1)->install_write_handler(0x7ff3, 0x7ff3, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w))); + page(1)->install_write_handler(0x7ff4, 0x7ff4, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::side_motor_w))); + page(1)->install_write_handler(0x7ff5, 0x7ff5, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::select0_w))); + page(1)->install_write_handler(0x7ff6, 0x7ff6, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::select1_w))); + + return std::error_condition(); +} + +void hxf101pe_device::device_post_load() +{ + select_drive(); +} + +void hxf101pe_device::select_drive() +{ + if (m_drive_select1) + { + m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr; + if (!m_floppy) + m_drive_select1 = 0; + } + + if (m_drive_select0) + { + m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr; + if (!m_floppy) + m_drive_select0 = 0; + } + + m_fdc->set_floppy(m_floppy); + + set_side_motor(); +} + +void hxf101pe_device::set_side_motor() +{ + if (m_floppy) + { + m_floppy->mon_w(BIT(m_side_motor, 1) ? 0 : 1); + m_floppy->ss_w(BIT(m_side_motor, 0)); + } +} + +u8 hxf101pe_device::side_motor_r() +{ + // bit 0 = side control + // bit 1 = motor control + return 0xfc | m_side_motor; +} + +u8 hxf101pe_device::select0_r() +{ + // This reads back a 1 in bit 0 if drive0 is present and selected + return 0xfe | m_drive_select0; +} + +u8 hxf101pe_device::select1_r() +{ + // This reads back a 1 in bit 0 if drive1 is present and selected + return 0xfe | m_drive_select1; +} + +u8 hxf101pe_device::status_r() +{ + return 0x3f | (m_fdc->intrq_r() ? 0 : 0x40) | (m_fdc->drq_r() ? 0 : 0x80); +} + +void hxf101pe_device::side_motor_w(u8 data) +{ + // Side and motor control + // bit 0 = side select + // bit 1 = motor on/off + m_side_motor = data; + set_side_motor(); +} + +void hxf101pe_device::select0_w(u8 data) +{ + // bit 0 - select drive 0 + m_drive_select0 = data; + select_drive(); +} + +void hxf101pe_device::select1_w(u8 data) +{ + // bit 1 - select drive 1 + m_drive_select1 = data; + select_drive(); +} + + + +class mfd001_device : public disk_wd_device +{ +public: + mfd001_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_wd_device(mconfig, MSX_CART_MFD001, tag, owner, clock) + , m_control(0) + { } + + virtual std::error_condition initialize_cartridge(std::string &message) override; + +protected: + // device_t implementation + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + virtual void device_post_load() override; + + void set_side_motor(); + void select_drive(); + u8 status_r(); + void control_w(u8 data); + + u8 m_control; +}; + +void mfd001_device::device_add_mconfig(machine_config &config) +{ + add_mconfig<F525, DS>(config, MB8877); +} + +std::error_condition mfd001_device::initialize_cartridge(std::string &message) +{ + std::error_condition result = disk_wd_device::initialize_cartridge(message); + if (result) + return result; + + page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base()); + + for (int i = m_fdc_regs_start_page; i <= m_fdc_regs_end_page; i++) + { + const offs_t base = 0x4000 * i; + page(i)->install_read_handler(base + 0x3ff8, base + 0x3ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r))); + page(i)->install_read_handler(base + 0x3ff9, base + 0x3ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r))); + page(i)->install_read_handler(base + 0x3ffa, base + 0x3ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r))); + page(i)->install_read_handler(base + 0x3ffb, base + 0x3ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r))); + page(i)->install_read_handler(base + 0x3ffc, base + 0x3ffc, emu::rw_delegate(*this, FUNC(mfd001_device::status_r))); + page(i)->install_write_handler(base + 0x3ff8, base + 0x3ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w))); + page(i)->install_write_handler(base + 0x3ff9, base + 0x3ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w))); + page(i)->install_write_handler(base + 0x3ffa, base + 0x3ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w))); + page(i)->install_write_handler(base + 0x3ffb, base + 0x3ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w))); + page(i)->install_write_handler(base + 0x3ffc, base + 0x3ffc, emu::rw_delegate(*this, FUNC(mfd001_device::control_w))); + } + + return std::error_condition(); +} + +void mfd001_device::device_start() +{ + save_item(NAME(m_control)); +} + +void mfd001_device::device_post_load() +{ + select_drive(); +} + +void mfd001_device::select_drive() +{ + if (BIT(m_control, 0)) + { + m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr; + } + + if (BIT(m_control, 1)) + { + m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr; + } + + m_fdc->set_floppy(m_floppy); + + if (m_floppy) + { + m_floppy->mon_w(BIT(m_control, 3) ? 0 : 1); + m_floppy->ss_w(BIT(m_control, 2)); + } +} + +u8 mfd001_device::status_r() +{ + return 0x3f | (m_fdc->intrq_r() ? 0x80 : 0) | (m_fdc->drq_r() ? 0x40 : 0); +} + +void mfd001_device::control_w(u8 data) +{ + // Drive, side and motor control + // bit 0 = select drive 0 + // bit 1 = select drive 1 + // bit 2 = side select + // bit 3 = motor on/off + m_control = data; + select_drive(); +} + + +class avdpf550_device : public disk_wd_device +{ +public: + avdpf550_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : disk_wd_device(mconfig, MSX_CART_AVDPF550, tag, owner, clock) + , m_control(0) + { } + + virtual std::error_condition initialize_cartridge(std::string &message) override; + +protected: + // device_t implementation + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + virtual void device_post_load() override; + + void control_w(u8 control); + virtual u8 status_r(); + + u8 m_control; +}; + +void avdpf550_device::device_add_mconfig(machine_config &config) +{ + WD1770(config, m_fdc, 8_MHz_XTAL); + add_floppy_mconfig<F525, SS>(config); +} + +void avdpf550_device::device_start() +{ + save_item(NAME(m_control)); +} + +std::error_condition avdpf550_device::initialize_cartridge(std::string &message) +{ + std::error_condition result = disk_wd_device::initialize_cartridge(message); + if (result) + return result; + + page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base()); + + // Install IO read/write handlers + io_space().install_write_handler(0xd0, 0xd0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w))); + io_space().install_write_handler(0xd1, 0xd1, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w))); + io_space().install_write_handler(0xd2, 0xd2, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w))); + io_space().install_write_handler(0xd3, 0xd3, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w))); + io_space().install_write_handler(0xd5, 0xd5, emu::rw_delegate(*this, FUNC(avdpf550_device::control_w))); + io_space().install_read_handler(0xd0, 0xd0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r))); + io_space().install_read_handler(0xd1, 0xd1, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r))); + io_space().install_read_handler(0xd2, 0xd2, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r))); + io_space().install_read_handler(0xd3, 0xd3, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r))); + io_space().install_read_handler(0xd4, 0xd4, emu::rw_delegate(*this, FUNC(avdpf550_device::status_r))); + + return std::error_condition(); +} + +void avdpf550_device::device_post_load() +{ + control_w(m_control); +} + +void avdpf550_device::control_w(u8 control) +{ + m_control = control; + + switch (m_control & 0x03) + { + case 0x01: + m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr; + break; + + case 0x02: + m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr; + break; + + default: + m_floppy = nullptr; + break; + } + + if (m_floppy) + { + m_floppy->mon_w(0); + m_floppy->ss_w(BIT(m_control, 2) ? 1 : 0); + } + + m_fdc->set_floppy(m_floppy); +} + +u8 avdpf550_device::status_r() +{ + return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0); +} + +} // anonymous namespace + + +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_AVDPF550, msx_cart_interface, avdpf550_device, "msx_cart_avdpf550", "MSX Cartridge - AVT DPF-550") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_CDX2, msx_cart_interface, cdx2_device, "msx_cart_cdx2", "MSX Cartridge - CDX-2") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_DDX3, msx_cart_interface, ddx3_device, "msx_cart_ddx3", "MSX Cartridge - DDX3.0") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FD03, msx_cart_interface, fd03_device, "msx_cart_fd03", "MSX Cartridge - FD-03") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FD051, msx_cart_interface, fd051_device, "msx_cart_fd051", "MSX Cartridge - FD-051") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FSFD1, msx_cart_interface, fsfd1_device, "msx_cart_fsfd1", "MSX Cartridge - FS-FD1") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FSFD1A, msx_cart_interface, fsfd1a_device, "msx_cart_fsfd1a", "MSX Cartridge - FS-FD1A") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FSCF351, msx_cart_interface, fscf351_device, "msx_cart_fscf351", "MSX Cartridge - FS-CF351") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HB3600, msx_cart_interface, hb3600_device, "msx_cart_hb3600", "MSX Cartridge - HB-3600") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HBD20W, msx_cart_interface, hbd20w_device, "msx_cart_hbd20w", "MSX Cartridge - HBD-20W") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HBD50, msx_cart_interface, hbd50_device, "msx_cart_hbd50", "MSX Cartridge - HBD-50") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HBDF1, msx_cart_interface, hbdf1_device, "msx_cart_hbdf1", "MSX Cartridge - HBD-F1") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HXF101PE, msx_cart_interface, hxf101pe_device, "msx_cart_hxf101pe", "MSX Cartridge - HX-F101PE") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MFD001, msx_cart_interface, mfd001_device, "msx_cart_mfd001", "MSX Cartridge - MFD-001") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_ML30DC, msx_cart_interface, ml30dc_device, "msx_cart_ml30dc", "MSX Cartridge - ML-30DC") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_NMS1200, msx_cart_interface, nms1200_device, "msx_cart_nms1200", "MSX Cartridge - NMS-1200") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_TADPF550, msx_cart_interface, tadpf550_device, "msx_cart_tadpf550", "MSX Cartridge - Talent DPF-550") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_VY0010, msx_cart_interface, vy0010_device, "msx_cart_vy0010", "MSX Cartridge - VY0010") |