From 97042aa7f9aae005636553e8629ec0d33892b910 Mon Sep 17 00:00:00 2001 From: MetalliC <0vetal0@gmail.com> Date: Sun, 12 Jul 2020 22:58:58 +0300 Subject: [PATCH] spectrum: add Logitek Proceed 1 C1541 disk interface (not fully working yet) --- scripts/src/bus.lua | 2 + src/devices/bus/spectrum/exp.cpp | 8 +- src/devices/bus/spectrum/logitek.cpp | 217 +++++++++++++++++++++++++ src/devices/bus/spectrum/logitek.h | 69 ++++++++ src/devices/bus/spectrum/speccydos.cpp | 5 +- src/devices/bus/spectrum/usource.cpp | 7 +- src/devices/bus/spectrum/uspeech.cpp | 48 +++--- src/lib/formats/sdd_dsk.cpp | 4 + src/mame/drivers/spectrum.cpp | 6 +- 9 files changed, 337 insertions(+), 29 deletions(-) create mode 100644 src/devices/bus/spectrum/logitek.cpp create mode 100644 src/devices/bus/spectrum/logitek.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index f2f992feb3f..935953f0781 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -3770,6 +3770,8 @@ if (BUSES["SPECTRUM"]~=null) then MAME_DIR .. "src/devices/bus/spectrum/kempjoy.h", MAME_DIR .. "src/devices/bus/spectrum/kempdisc.cpp", MAME_DIR .. "src/devices/bus/spectrum/kempdisc.h", + MAME_DIR .. "src/devices/bus/spectrum/logitek.cpp", + MAME_DIR .. "src/devices/bus/spectrum/logitek.h", MAME_DIR .. "src/devices/bus/spectrum/melodik.cpp", MAME_DIR .. "src/devices/bus/spectrum/melodik.h", MAME_DIR .. "src/devices/bus/spectrum/mface.cpp", diff --git a/src/devices/bus/spectrum/exp.cpp b/src/devices/bus/spectrum/exp.cpp index 9fc8e78a1a4..77a5b6bd227 100644 --- a/src/devices/bus/spectrum/exp.cpp +++ b/src/devices/bus/spectrum/exp.cpp @@ -169,6 +169,7 @@ void spectrum_expansion_slot_device::mreq_w(offs_t offset, uint8_t data) #include "mikroplus.h" #include "opus.h" #include "plus2test.h" +#include "logitek.h" #include "protek.h" #include "specdrum.h" #include "speccydos.h" @@ -186,6 +187,9 @@ void spectrum_expansion_devices(device_slot_interface &device) device.option_add("betacbi", SPECTRUM_BETACBI); device.option_add("gamma", SPECTRUM_GAMMA); device.option_add("beta128", SPECTRUM_BETA128); + device.option_add("d40", SPECTRUM_D40); + device.option_add("d80", SPECTRUM_D80); + device.option_add("d80v2", SPECTRUM_D80V2); device.option_add("disciple", SPECTRUM_DISCIPLE); device.option_add("intf1", SPECTRUM_INTF1); device.option_add("intf2", SPECTRUM_INTF2); @@ -200,9 +204,7 @@ void spectrum_expansion_devices(device_slot_interface &device) device.option_add("mprint", SPECTRUM_MPRINT); device.option_add("opus", SPECTRUM_OPUS); device.option_add("plusd", SPECTRUM_PLUSD); - device.option_add("d40", SPECTRUM_D40); - device.option_add("d80", SPECTRUM_D80); - device.option_add("d80v2", SPECTRUM_D80V2); + device.option_add("proceed", SPECTRUM_PROCEED); device.option_add("protek", SPECTRUM_PROTEK); device.option_add("speccydos", SPECTRUM_SPECCYDOS); device.option_add("specdrum", SPECTRUM_SPECDRUM); diff --git a/src/devices/bus/spectrum/logitek.cpp b/src/devices/bus/spectrum/logitek.cpp new file mode 100644 index 00000000000..2549e112649 --- /dev/null +++ b/src/devices/bus/spectrum/logitek.cpp @@ -0,0 +1,217 @@ +// license:BSD-3-Clause +// copyright-holders:MetalliC +/********************************************************************* + + Proceed 1 - Commodore IEC Bus and printer interface + (c) 1984 Logitek (Germany) + + Allows to connect and use Commodore 1541 disk drive. + Components: Z8420 PIO, 8K ROM, 256x4 PROM, NMI button. + + Photos and manual https://k1.spdns.de/Vintage/Sinclair/82/Peripherals/Disc%20Interfaces/Logitek%20Proceed%201%20C64%20Disc%20Interface/ + + Notes / TODOs: + - floppy drive access doesn't works with "Device timeout" error message. + cause is not known, possible due to not correct IEC hookup or some Z80PIO emulation bugs. + + - ROM paging performed by undumped PROM, current logic might be incorrect or innacurate. + wiring: A0-A5 - Z80 A8-A13, A6 - PIO PB7, A7 - nc, /CE1 - A14, /CE2 - A15, + Q1 - ROM A11, Q2 - ROM A10, Q3 - ROM /CE, Q4 - /ROMCS + +*********************************************************************/ + +#include "emu.h" +#include "logitek.h" + + +/*************************************************************************** + DEVICE DEFINITIONS +***************************************************************************/ + +DEFINE_DEVICE_TYPE(SPECTRUM_PROCEED, spectrum_proceed_device, "spectrum_proceed", "Proceed 1 Interface") + + +//------------------------------------------------- +// INPUT_PORTS +//------------------------------------------------- + +INPUT_PORTS_START(proceed) + PORT_START("BUTTON") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("NMI Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_proceed_device, nmi_button, 0) +INPUT_PORTS_END + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor spectrum_proceed_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(proceed); +} + +//------------------------------------------------- +// ROM( proceed ) +//------------------------------------------------- + +ROM_START(proceed) + ROM_REGION(0x2000, "rom", 0) + ROM_DEFAULT_BIOS("ldos21") + + ROM_SYSTEM_BIOS(0, "ldos21", "LDOS v2.1") + ROMX_LOAD("ldos_v21.bin", 0x0000, 0x2000, CRC(a7c47bac) SHA1(c999b0e4f5537405ed56c4c96beca5e7f5eb2b1e), ROM_BIOS(0)) +ROM_END + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void spectrum_proceed_device::device_add_mconfig(machine_config &config) +{ + Z80PIO(config, m_z80pio, 3500000); + m_z80pio->out_pa_callback().set(FUNC(spectrum_proceed_device::pioa_w)); + m_z80pio->in_pb_callback().set(FUNC(spectrum_proceed_device::piob_r)); // this works + m_z80pio->out_pb_callback().set(FUNC(spectrum_proceed_device::piob_w)); + m_z80pio->out_int_callback().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w)); + + cbm_iec_slot_device::add(config, m_iec, "c1541"); + //m_iec->clk_callback().set(m_z80pio, FUNC(z80pio_device::pb3_w)); // this not working, pio bugs ? + //m_iec->data_callback().set(m_z80pio, FUNC(z80pio_device::pb2_w)); + + CENTRONICS(config, m_centronics, centronics_devices, "printer"); + m_centronics->busy_handler().set(m_z80pio, FUNC(z80pio_device::pb0_w)); +} + +const tiny_rom_entry *spectrum_proceed_device::device_rom_region() const +{ + return ROM_NAME(proceed); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// spectrum_proceed_device - constructor +//------------------------------------------------- + +spectrum_proceed_device::spectrum_proceed_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, SPECTRUM_PROCEED, tag, owner, clock) + , device_spectrum_expansion_interface(mconfig, *this) + , m_rom(*this, "rom") + , m_z80pio(*this, "z80pio") + , m_iec(*this, "iec_bus") + , m_centronics(*this, "centronics") +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void spectrum_proceed_device::device_start() +{ + save_item(NAME(m_romcs)); + save_item(NAME(m_romen)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void spectrum_proceed_device::device_reset() +{ + m_romcs = 0; + m_romen = 0; + m_iec->reset(); +} + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +READ_LINE_MEMBER(spectrum_proceed_device::romcs) +{ + return m_romcs; +} + +uint8_t spectrum_proceed_device::mreq_r(offs_t offset) +{ + u8 data = 0xff; + + switch (offset >> 8) + { + // always override + case 0x00: + case 0x0e: + case 0x39: case 0x3a: case 0x3b: case 0x3c: + m_romcs = 1; + break; + case 0x1b: + m_romcs = 1; + offset |= 0x0400; // 1Bxx -> 1Fxx + break; + // override only if PIO PB7 is 0 + case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: + case 0x0f: case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: + case 0x1d: case 0x1e: + m_romcs = m_romen; + break; + + default: + m_romcs = 0; + } + + if (m_romcs) + data = m_rom->base()[offset & 0x1fff]; + + return data; +} + +uint8_t spectrum_proceed_device::iorq_r(offs_t offset) +{ + uint8_t data = 0xff; + + if (!BIT(offset, 5)) + data = m_z80pio->read((offset >> 6) & 3); + + return data; +} + +void spectrum_proceed_device::iorq_w(offs_t offset, uint8_t data) +{ + if (!BIT(offset, 5)) + m_z80pio->write((offset >> 6) & 3, data); +} + +void spectrum_proceed_device::pioa_w(uint8_t data) +{ + m_centronics->write_data0(BIT(data, 0)); + m_centronics->write_data1(BIT(data, 1)); + m_centronics->write_data2(BIT(data, 2)); + m_centronics->write_data3(BIT(data, 3)); + m_centronics->write_data4(BIT(data, 4)); + m_centronics->write_data5(BIT(data, 5)); + m_centronics->write_data6(BIT(data, 6)); + m_centronics->write_data7(BIT(data, 7)); +} + +uint8_t spectrum_proceed_device::piob_r() +{ + u8 data = 0xf2; + + data |= m_iec->clk_r() << 3; + data |= m_iec->data_r() << 2; + + return data; +} + +void spectrum_proceed_device::piob_w(uint8_t data) +{ + m_romen = !BIT(data, 7); + m_iec->host_atn_w(BIT(data, 6)); + m_iec->host_clk_w(BIT(data, 5)); + m_iec->host_data_w(BIT(data, 4)); + m_centronics->write_strobe(BIT(data, 1)); + //logerror("PB %02X\n", data); +} diff --git a/src/devices/bus/spectrum/logitek.h b/src/devices/bus/spectrum/logitek.h new file mode 100644 index 00000000000..94d5393800f --- /dev/null +++ b/src/devices/bus/spectrum/logitek.h @@ -0,0 +1,69 @@ +// license:BSD-3-Clause +// copyright-holders:MetalliC +/********************************************************************* + + Proceed 1 Interface + (c) 1984 Logitek + +*********************************************************************/ +#ifndef MAME_BUS_SPECTRUM_LOGITEK_H +#define MAME_BUS_SPECTRUM_LOGITEK_H + +#include "exp.h" +#include "softlist.h" +#include "machine/z80pio.h" +#include "bus/cbmiec/cbmiec.h" +#include "bus/centronics/ctronics.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class spectrum_proceed_device : + public device_t, + public device_spectrum_expansion_interface + +{ +public: + // construction/destruction + spectrum_proceed_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + static constexpr feature_type unemulated_features() { return feature::DISK; } + + DECLARE_INPUT_CHANGED_MEMBER(nmi_button) { m_slot->nmi_w(newval ? ASSERT_LINE : CLEAR_LINE); }; + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // optional information overrides + virtual ioport_constructor device_input_ports() const override; + + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + + virtual uint8_t mreq_r(offs_t offset) override; + virtual uint8_t iorq_r(offs_t offset) override; + virtual void iorq_w(offs_t offset, uint8_t data) override; + virtual DECLARE_READ_LINE_MEMBER(romcs) override; + + required_memory_region m_rom; + required_device m_z80pio; + required_device m_iec; + required_device m_centronics; + + void pioa_w(uint8_t data); + void piob_w(uint8_t data); + uint8_t piob_r(); + + int m_romcs; + int m_romen; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(SPECTRUM_PROCEED, spectrum_proceed_device) + + +#endif // MAME_BUS_SPECTRUM_LOGITEK_H diff --git a/src/devices/bus/spectrum/speccydos.cpp b/src/devices/bus/spectrum/speccydos.cpp index 76fa5dc4956..749a6993c0b 100644 --- a/src/devices/bus/spectrum/speccydos.cpp +++ b/src/devices/bus/spectrum/speccydos.cpp @@ -103,8 +103,8 @@ void spectrum_speccydos_device::device_add_mconfig(machine_config &config) { WD1770(config, m_fdc, 8_MHz_XTAL); - FLOPPY_CONNECTOR(config, "fdc:0", speccydos_floppies, "35dsdd", spectrum_speccydos_device::floppy_formats).enable_sound(true); - FLOPPY_CONNECTOR(config, "fdc:1", speccydos_floppies, "35dsdd", spectrum_speccydos_device::floppy_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:0", speccydos_floppies, "525dsqd", spectrum_speccydos_device::floppy_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:1", speccydos_floppies, "525dsqd", spectrum_speccydos_device::floppy_formats).enable_sound(true); FLOPPY_CONNECTOR(config, "fdc:2", speccydos_floppies, nullptr, spectrum_speccydos_device::floppy_formats).enable_sound(true); FLOPPY_CONNECTOR(config, "fdc:3", speccydos_floppies, nullptr, spectrum_speccydos_device::floppy_formats).enable_sound(true); @@ -178,6 +178,7 @@ void spectrum_speccydos_device::pre_opcode_fetch(offs_t offset) { switch (offset) { + case 0x0066: case 0x1292: case 0x1b41: if (!BIT(m_control, 6)) diff --git a/src/devices/bus/spectrum/usource.cpp b/src/devices/bus/spectrum/usource.cpp index 4acee2141cd..3c368297fef 100644 --- a/src/devices/bus/spectrum/usource.cpp +++ b/src/devices/bus/spectrum/usource.cpp @@ -93,5 +93,10 @@ void spectrum_usource_device::pre_opcode_fetch(offs_t offset) uint8_t spectrum_usource_device::mreq_r(offs_t offset) { - return m_rom->base()[offset & 0x1fff]; + u8 data = 0xff; + + if (m_romcs) + data = m_rom->base()[offset & 0x1fff]; + + return data; } diff --git a/src/devices/bus/spectrum/uspeech.cpp b/src/devices/bus/spectrum/uspeech.cpp index d3476bbc441..a3a6db8cb30 100644 --- a/src/devices/bus/spectrum/uspeech.cpp +++ b/src/devices/bus/spectrum/uspeech.cpp @@ -121,14 +121,17 @@ uint8_t spectrum_uspeech_device::mreq_r(offs_t offset) { uint8_t data = 0xff; - switch (offset & 0xf000) + if (m_romcs) { - case 0x0000: - data = m_rom->base()[offset & 0x7ff]; - break; - case 0x1000: - data = !m_nsp->lrq_r(); - break; + switch (offset & 0xf000) + { + case 0x0000: + data = m_rom->base()[offset & 0x7ff]; + break; + case 0x1000: + data = !m_nsp->lrq_r(); + break; + } } return data; @@ -136,22 +139,25 @@ uint8_t spectrum_uspeech_device::mreq_r(offs_t offset) void spectrum_uspeech_device::mreq_w(offs_t offset, uint8_t data) { - switch (offset & 0xf001) + if (m_romcs) { - case 0x1000: - case 0x1001: - // allophone - m_nsp->ald_w(data & 0x3f); - break; + switch (offset & 0xf001) + { + case 0x1000: + case 0x1001: + // allophone + m_nsp->ald_w(data & 0x3f); + break; - case 0x3000: - // intonation low - m_nsp->set_clock(3050000); // oscillator frequency read from hardware - break; + case 0x3000: + // intonation low + m_nsp->set_clock(3050000); // oscillator frequency read from hardware + break; - case 0x3001: - // intonation high - m_nsp->set_clock(3260000); // oscillator frequency read from hardware - break; + case 0x3001: + // intonation high + m_nsp->set_clock(3260000); // oscillator frequency read from hardware + break; + } } } diff --git a/src/lib/formats/sdd_dsk.cpp b/src/lib/formats/sdd_dsk.cpp index 5159cd6e2bc..cac33948db0 100644 --- a/src/lib/formats/sdd_dsk.cpp +++ b/src/lib/formats/sdd_dsk.cpp @@ -41,6 +41,10 @@ const sdd_format::format sdd_format::formats[] = { floppy_image::FF_525, floppy_image::DSQD, floppy_image::MFM, 2000, 16, 80, 2, 256, {}, -1, {1,12,7,2,13,8,3,14,9,4,15,10,5,16,11,6}, 60, 22, 24 }, + { // 5"25 140K 35 track single sided double density + floppy_image::FF_525, floppy_image::SSDD, floppy_image::MFM, + 2000, 16, 35, 1, 256, {}, -1, {1,12,7,2,13,8,3,14,9,4,15,10,5,16,11,6}, 60, 22, 24 + }, { // 5"25 400K 80 track double sided single density floppy_image::FF_525, floppy_image::DSQD, floppy_image::FM, 4000, 10, 80, 2, 256, {}, -1, {1,8,5,2,9,6,3,10,7,4}, 40, 11, 10 diff --git a/src/mame/drivers/spectrum.cpp b/src/mame/drivers/spectrum.cpp index 65dcbab6e65..8af955f6b29 100644 --- a/src/mame/drivers/spectrum.cpp +++ b/src/mame/drivers/spectrum.cpp @@ -323,10 +323,12 @@ void spectrum_state::spectrum_rom_w(offs_t offset, uint8_t data) uint8_t spectrum_state::spectrum_rom_r(offs_t offset) { - uint8_t data; + uint8_t data, edata; + + edata = m_exp->mreq_r(offset); if (m_exp->romcs()) - data = m_exp->mreq_r(offset); + data = edata; else data = memregion("maincpu")->base()[offset];