diff options
Diffstat (limited to 'src/devices/bus/spectrum/floppyone.cpp')
-rw-r--r-- | src/devices/bus/spectrum/floppyone.cpp | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/src/devices/bus/spectrum/floppyone.cpp b/src/devices/bus/spectrum/floppyone.cpp new file mode 100644 index 00000000000..2bf11a8c27e --- /dev/null +++ b/src/devices/bus/spectrum/floppyone.cpp @@ -0,0 +1,282 @@ +// license:BSD-3-Clause +// copyright-holders:MetalliC +/********************************************************************* + + FloppyOne DOS Interface + (c) 1984/5 Rocky P. Gush + + FD1791-based floppy drive and printer interface with 4K RAM and 8K ROM + Was mainly designed as tape replacement, and sort of emulate how tapes works, + which allows to copy and use most of existing software and (not protected) games with no modification. + + Doube-side drives considered as 2 separate floppies (0 and 4, 1 and 5 etc) probably to mimic tape sides A/B, + disks is password protected. + + Main commands: + !D=n - change current drive, where 'n' 0-3 = FDD 0-3 side 0, 4-7 = FDD 0-3 side 1, 8 = enable LOAD from tape + CAT - list disk contents + LOAD "name" - load program, LOAD "" will load first program (unless was disabled by !d=8 command) + LOAD *"m";1;"name" - same as above + SAVE "name" - save program + !FORMAT "diskname";"password";tracks - format disk, if disk was already formatted you'll be prompted for password. + !6=n - set text mode, 0 - regular 32-column, 3 - 64-column + There is more of special "!x=n" commands, but theirs functions is not known, manual is missing. + Some information about this device https://worldofspectrum.org/forums/discussion/42944/rocky-gush-floppy-drive-interface/p1 + + Notes / TODOs: + - Interface1 compatibility mode is not well understood and not fully implemented + - Serial printer interface not implemented + +*********************************************************************/ + +#include "emu.h" +#include "floppyone.h" + + +/*************************************************************************** + DEVICE DEFINITIONS +***************************************************************************/ + +DEFINE_DEVICE_TYPE(SPECTRUM_FLPONE, spectrum_flpone_device, "spectrum_flpone", "FloppyOne DOS Interface") + + +//------------------------------------------------- +// INPUT_PORTS +//------------------------------------------------- + +INPUT_PORTS_START(flpone) + PORT_START("BUTTON") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Snapshot Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_flpone_device, snapshot_button, 0) + + PORT_START("SW1") + PORT_CONFNAME(0x01, 0x01, "Disc Interface") + PORT_CONFSETTING(0x01, "Enabled") + PORT_CONFSETTING(0x00, "Disabled") + PORT_START("SW2") + PORT_CONFNAME(0x01, 0x00, "Interface 1") + PORT_CONFSETTING(0x01, "Enable") + PORT_CONFSETTING(0x00, "Disable") +INPUT_PORTS_END + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor spectrum_flpone_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(flpone); +} + +//------------------------------------------------- +// SLOT_INTERFACE( floppies ) +//------------------------------------------------- + +static void flpone_floppies(device_slot_interface &device) +{ + device.option_add("525ssdd", FLOPPY_525_SSDD); + device.option_add("525dd", FLOPPY_525_DD); + device.option_add("525ssqd", FLOPPY_525_SSQD); + device.option_add("525qd", FLOPPY_525_QD); + device.option_add("35ssdd", FLOPPY_35_SSDD); + device.option_add("35dd", FLOPPY_35_DD); +} + +//------------------------------------------------- +// floppy_format_type floppy_formats +//------------------------------------------------- + +FLOPPY_FORMATS_MEMBER(spectrum_flpone_device::floppy_formats) + FLOPPY_FL1_FORMAT +FLOPPY_FORMATS_END + +//------------------------------------------------- +// ROM( flpone ) +//------------------------------------------------- + +ROM_START(flpone) + ROM_REGION(0x2000, "rom", 0) + ROM_DEFAULT_BIOS("v4") + + ROM_SYSTEM_BIOS(0, "v4", "FloppyOne DOS V4") + ROMX_LOAD("fldos4.bin", 0x0000, 0x2000, CRC(a012f64f) SHA1(f54b47d83c1d45c0e1e10302e519693bc734ae5c), ROM_BIOS(0)) + + ROM_REGION(0x4000, "prom", 0) + ROM_LOAD("ula.bin", 0x0000, 0x2000, CRC(d67d85aa) SHA1(eb1d28bf8aa35bfab3a45a5827f252498ac2c651)) // 1st half is not used, A13 tied to Vcc + ROM_CONTINUE(0x0000, 0x2000) +ROM_END + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void spectrum_flpone_device::device_add_mconfig(machine_config &config) +{ + FD1791(config, m_fdc, 1_MHz_XTAL); + + FLOPPY_CONNECTOR(config, "fdc:0", flpone_floppies, "525qd", spectrum_flpone_device::floppy_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:1", flpone_floppies, "525qd", spectrum_flpone_device::floppy_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:2", flpone_floppies, nullptr, spectrum_flpone_device::floppy_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:3", flpone_floppies, nullptr, spectrum_flpone_device::floppy_formats).enable_sound(true); + + // passthru + SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr); + m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w)); + m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w)); +} + +const tiny_rom_entry *spectrum_flpone_device::device_rom_region() const +{ + return ROM_NAME(flpone); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// spectrum_flpone_device - constructor +//------------------------------------------------- + +spectrum_flpone_device::spectrum_flpone_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, SPECTRUM_FLPONE, tag, owner, clock) + , device_spectrum_expansion_interface(mconfig, *this) + , m_rom(*this, "rom") + , m_prom(*this, "prom") + , m_fdc(*this, "fdc") + , m_floppy(*this, "fdc:%u", 0) + , m_exp(*this, "exp") + , m_sw1(*this, "SW1") + , m_sw2(*this, "SW2") +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void spectrum_flpone_device::device_start() +{ + memset(m_ram, 0, sizeof(m_ram)); + + save_item(NAME(m_romcs)); + save_item(NAME(m_ram)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void spectrum_flpone_device::device_reset() +{ + m_romcs = 0; + m_if1cs = 0; +} + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +READ_LINE_MEMBER(spectrum_flpone_device::romcs) +{ + return m_romcs | m_exp->romcs(); +} + +void spectrum_flpone_device::post_opcode_fetch(offs_t offset) +{ + m_exp->post_opcode_fetch(offset); + + if (!machine().side_effects_disabled() && m_sw1->read()) + { + if (offset < 0x2000) + { + u8 data = m_prom->base()[offset]; + m_romcs |= BIT(data, 4) ^ 1; + m_romcs &= BIT(data, 6); + if (m_sw2->read()) + { + m_if1cs |= BIT(data, 7) ^ 1; + m_if1cs &= BIT(data, 5); + m_romcs &= !m_if1cs; + } + } + } +} + +uint8_t spectrum_flpone_device::mreq_r(offs_t offset) +{ + u8 data = 0xff; + + if (m_romcs) + { + switch (offset & 0xf000) + { + case 0x0000: case 0x1000: + data = m_rom->base()[offset]; + break; + case 0x3000: + data = m_ram[offset & 0xfff]; + break; + case 0x2000: + switch (offset & 0xc) + { + case 0: case 8: + data = m_fdc->read(offset & 3); + break; + case 4: // D5 - printer BUSY / /BUSY + data = 0; + break; + case 0xc: // printer STROBE pulse + break; + } + break; + } + } + + if (m_exp->romcs()) + data &= m_exp->mreq_r(offset); + + return data; +} + +void spectrum_flpone_device::mreq_w(offs_t offset, uint8_t data) +{ + if (m_romcs) + { + switch (offset & 0xf000) + { + case 0x3000: + m_ram[offset & 0xfff] = data; + break; + case 0x2000: + switch (offset & 0xc) + { + case 0: case 8: + m_fdc->write(offset & 3, data); + break; + case 4: // D7 - printer serial data + break; + case 0xc: + { + floppy_image_device* floppy = nullptr; + for (int i = 3; i >= 0; i--) + { + floppy_image_device* fl = m_floppy[i]->get_device(); + if (fl) + { + fl->ss_w(BIT(data, 4)); + fl->mon_w((BIT(data, 5) && BIT(data, i)) ? CLEAR_LINE : ASSERT_LINE); + if (BIT(data, i)) + floppy = fl; + } + } + m_fdc->set_floppy(floppy); + } + break; + } + break; + } + } + + m_exp->mreq_w(offset, data); +} |