summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
authorGravatarGravatar Tom <37988779+TwistedTom@users.noreply.github.com>2019-11-11 11:44:03 +0000
committerGravatarGravatar Vas Crabb <cuavas@users.noreply.github.com>2019-11-11 22:44:03 +1100
commit4f0dd32003888ab2a70f40ed79a85e74f23f1369 (patch)
tree0cc5266d870e0461550cc39056fb9d05bf4084fa /src/devices
parent0a83f32207dfd827b59df245258cf1b133537947 (diff)
ZX Spectrum Multiface One improvements (#5885)
* mface * mface improvements * use required_ioport, remove disable switch
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/bus/spectrum/mface.cpp187
-rw-r--r--src/devices/bus/spectrum/mface.h36
2 files changed, 190 insertions, 33 deletions
diff --git a/src/devices/bus/spectrum/mface.cpp b/src/devices/bus/spectrum/mface.cpp
index 807787126b2..1417c5db58c 100644
--- a/src/devices/bus/spectrum/mface.cpp
+++ b/src/devices/bus/spectrum/mface.cpp
@@ -2,7 +2,81 @@
// copyright-holders:Nigel Barnes
/*********************************************************************
- Romantic Robot Multiface One/128/3
+ Romantic Robot Multiface One/128/3
+ ----------------------------------
+
+ " MULTI-PURPOSE INTERFACE FOR THE ZX SPECTRUM "
+
+ MULTIFACE ONE comprises three interfaces in one box:
+ 1) Fully universal and 100% automatic SAVE facility for tape, microdrive, wafadrive, Beta,
+ Discovery and indirectly (via tape) for other disc systems
+ 2) Joystick interface – Kempston compatible (IN 31)
+ 3) 8K RAM extension – fully accessible, usable as a RAM disk, buffer etc. Also used by
+ MULTIFACE for MULTI TOOLKIT routines, buffer & other purposes.
+
+ © Romantic Robot UK Ltd 1985
+
+
+ Multiface One
+ -------------
+ Many versions exist, a very good source of info is: https://x128.speccy.cz/multiface/multiface.htm
+
+ Summary:
+ Earliest version has 2KB of RAM, composite video output, and no toolkit (pokes only).
+ Next version has 8KB of RAM, composite video output, and basic toolkit (including pokes).
+ Latest and most common version dropped the composite video output, added an enable/disable switch, and full-featured toolkit.
+ A special (and rare) version supports the Kempston Disc interface but drops Beta support. (not sold in stores, available only on request).
+ At some point during "early" revisions, the page out port changed from 0x5f to 0x1f.
+ Various clone/hacked rom versions are known to exist as well.
+
+ Roms:
+ The MUxx in the rom name is pcb revision (silkscreen marking).
+ The two hex digits are the rom checksum.
+ With the MF menu on-screen, press Symbol Shift + A (STOP) to see checksum, space to return.
+
+ The enable/disable switch became necessary on later versions as games had started including checks to detect presence of the interface.
+ eg. Renegade ("The Hit Squad" re-release) whilst loading, reads from 0x9f specifically to cause the MF (if present) to page in and crash the machine.
+ Todo: confirm exact operation of disable switch.
+
+ As mentioned in the user instructions, there is a "joystick disable" jumper inside the unit which must be cut to allow Beta disk compatibility.
+ The joystick is not actually disabled but rather just data bus bits D6 + D7 are held hi-z for any reads of kempston range 0b000xxxxx.
+
+ rom maps to 0x0000
+ ram maps to 0x2000
+
+ I/O R/W early ver late ver
+ ---------+-----+-----------+-----------
+ page in R 0x9f 0x9f
+ page out R 0x5f 0x1f
+ nmi reset W 0x5f 0x1f
+ joystick R 0x1f 0x1f
+
+
+ Multiface 128
+ -------------
+ 128K/+2 support (also works with 48K)
+ DISCiPLE/Plus D disc support
+ No joystick port
+ Software enable/disable
+ "Hypertape" recording (?)
+
+ Todo ...
+
+
+ Multiface 3
+ -----------
+ +2A/+2B/+3/3B support (doesn't work with 48K/128K/+2)
+ +3 disk support
+
+ Todo ...
+
+
+ Multiprint
+ ----------
+ Version ? multiface with Centronics printer interface
+
+ Todo ...
+
*********************************************************************/
@@ -24,37 +98,74 @@ DEFINE_DEVICE_TYPE(SPECTRUM_MPRINT, spectrum_mprint_device, "spectrum_mprint", "
// INPUT_PORTS( mface )
//-------------------------------------------------
-INPUT_PORTS_START(mface)
+INPUT_PORTS_START( mface )
PORT_START("BUTTON")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Multiface") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_mface1_device, magic_button, 0)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Red Button") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_mface_base_device, magic_button, 0)
+INPUT_PORTS_END
+
+INPUT_PORTS_START( mface1 )
+ PORT_INCLUDE( mface )
+
+ PORT_START("CONFIG")
+ PORT_CONFNAME(0x01, 0x00, "Joystick Enable Jumper")
+ PORT_CONFSETTING(0x00, "Closed")
+ PORT_CONFSETTING(0x01, "Open")
+ PORT_BIT(0xfe, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("JOY")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_8WAY
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_8WAY
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_8WAY
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_8WAY
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_BUTTON1)
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
-ioport_constructor spectrum_mface1_device::device_input_ports() const
+ioport_constructor spectrum_mface_base_device::device_input_ports() const
{
return INPUT_PORTS_NAME(mface);
}
+ioport_constructor spectrum_mface1_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mface1);
+}
+
//-------------------------------------------------
-// ROM( mface1 )
+// ROM( mface )
//-------------------------------------------------
ROM_START(mface1)
ROM_REGION(0x2000, "rom", 0)
ROM_DEFAULT_BIOS("mu21e7")
- ROM_SYSTEM_BIOS(0, "mu20fe", "MU 2.0 FE")
+ ROM_SYSTEM_BIOS(0, "mu20fe", "MU 2.0 FE") // pokes only (no toolkit)
ROMX_LOAD("mf1_20_fe.rom", 0x0000, 0x2000, CRC(fa1b8b0d) SHA1(20cd508b0143166558a7238c7a9ccfbe37b90b0d), ROM_BIOS(0))
- ROM_SYSTEM_BIOS(1, "mu2167", "MU 2.1 67")
+ ROM_SYSTEM_BIOS(1, "mu2167", "MU 2.1 67") // Kempston Disc support, no Beta support
ROMX_LOAD("mf1_21_67.rom", 0x0000, 0x2000, CRC(d720ec1b) SHA1(91a40d8f503ef825df3e2ed712897dbf4ca3671d), ROM_BIOS(1))
- ROM_SYSTEM_BIOS(2, "mu21e4", "MU 2.1 E4")
+ ROM_SYSTEM_BIOS(2, "mu21e4", "MU 2.1 E4") // the most common version
ROMX_LOAD("mf1_21_e4.rom", 0x0000, 0x2000, CRC(4b31a971) SHA1(ba28754a3cc31a4ca579829ed4310c313409cf5d), ROM_BIOS(2))
- ROM_SYSTEM_BIOS(3, "mu21e7", "MU 2.1 E7")
+ ROM_SYSTEM_BIOS(3, "mu21e7", "MU 2.1 E7") // last known version?
ROMX_LOAD("mf1_21_e7.rom", 0x0000, 0x2000, CRC(670f0ec2) SHA1(50fba2d628f3a2e9219f72980e4efd62fc9ec1f8), ROM_BIOS(3))
ROM_END
+/* Todo ...
+
+ ROM_SYSTEM_BIOS(?, "mu12cb", "MU12 CB") // Very early version, 2KB RAM, page out port 0x5F
+ ROMX_LOAD("mf1_12_cb.rom", 0x0000, 0x2000, CRC(c88fbf9f) SHA1(c3018d1b495b8bc0a135038db0987de7091c9d4c), ROM_BIOS(?))
+
+ ROM_SYSTEM_BIOS(?, "mu2023", "MU 2.0 23") // pokes only (no toolkit), page out port 0x5F
+ ROMX_LOAD("mf1_20_23.rom", 0x0000, 0x2000, CRC(d4ae8953) SHA1(b442eb634a72fb63f1ccbbd0021a7a581152888d), ROM_BIOS(?))
+
+ ROM_SYSTEM_BIOS(?, "mu2090", "MU 2.0, 90") // pokes only or full toolkit? NO DUMP?
+ ROMX_LOAD("mf1_20_90.rom", 0x0000, 0x2000, CRC(2eaf8e41) SHA1(?), ROM_BIOS(?))
+
+ ROM_SYSTEM_BIOS(?, "v24", "MU ?? 93 (Brazilian clone)") // NO DUMP?
+ ROMX_LOAD("mf1_bc_fe.rom", 0x0000, 0x2000, CRC(8c17113b) SHA1(?), ROM_BIOS(?))
+*/
+
ROM_START(mface128)
ROM_REGION(0x2000, "rom", 0)
ROM_DEFAULT_BIOS("v363c")
@@ -84,7 +195,7 @@ ROM_END
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void spectrum_mface1_device::device_add_mconfig(machine_config &config)
+void spectrum_mface_base_device::device_add_mconfig(machine_config &config)
{
/* passthru */
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
@@ -118,10 +229,10 @@ const tiny_rom_entry *spectrum_mprint_device::device_rom_region() const
//**************************************************************************
//-------------------------------------------------
-// spectrum_opus_device - constructor
+// spectrum_mface_base_device - constructor
//-------------------------------------------------
-spectrum_mface1_device::spectrum_mface1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+spectrum_mface_base_device::spectrum_mface_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_spectrum_expansion_interface(mconfig, *this)
, m_rom(*this, "rom")
@@ -130,22 +241,24 @@ spectrum_mface1_device::spectrum_mface1_device(const machine_config &mconfig, de
}
spectrum_mface1_device::spectrum_mface1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : spectrum_mface1_device(mconfig, SPECTRUM_MFACE1, tag, owner, clock)
+ : spectrum_mface_base_device(mconfig, SPECTRUM_MFACE1, tag, owner, clock)
+ , m_joy(*this, "JOY")
+ , m_hwconfig(*this, "CONFIG")
{
}
spectrum_mface128_device::spectrum_mface128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : spectrum_mface1_device(mconfig, SPECTRUM_MFACE128, tag, owner, clock)
+ : spectrum_mface_base_device(mconfig, SPECTRUM_MFACE128, tag, owner, clock)
{
}
spectrum_mface3_device::spectrum_mface3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : spectrum_mface1_device(mconfig, SPECTRUM_MFACE3, tag, owner, clock)
+ : spectrum_mface_base_device(mconfig, SPECTRUM_MFACE3, tag, owner, clock)
{
}
spectrum_mprint_device::spectrum_mprint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : spectrum_mface1_device(mconfig, SPECTRUM_MPRINT, tag, owner, clock)
+ : spectrum_mface_base_device(mconfig, SPECTRUM_MPRINT, tag, owner, clock)
{
}
@@ -153,7 +266,7 @@ spectrum_mprint_device::spectrum_mprint_device(const machine_config &mconfig, co
// device_start - device-specific startup
//-------------------------------------------------
-void spectrum_mface1_device::device_start()
+void spectrum_mface_base_device::device_start()
{
save_item(NAME(m_romcs));
}
@@ -162,7 +275,7 @@ void spectrum_mface1_device::device_start()
// device_reset - device-specific reset
//-------------------------------------------------
-void spectrum_mface1_device::device_reset()
+void spectrum_mface_base_device::device_reset()
{
m_romcs = 0;
}
@@ -172,12 +285,12 @@ void spectrum_mface1_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_mface1_device::romcs)
+READ_LINE_MEMBER(spectrum_mface_base_device::romcs)
{
return m_romcs | m_exp->romcs();
}
-void spectrum_mface1_device::pre_opcode_fetch(offs_t offset)
+void spectrum_mface_base_device::pre_opcode_fetch(offs_t offset)
{
m_exp->pre_opcode_fetch(offset);
@@ -191,13 +304,15 @@ void spectrum_mface1_device::pre_opcode_fetch(offs_t offset)
uint8_t spectrum_mface1_device::iorq_r(offs_t offset)
{
uint8_t data = m_exp->iorq_r(offset);
-
+
if (!machine().side_effects_disabled())
{
switch (offset & 0xff)
{
case 0x1f:
m_romcs = 0;
+ if (!(m_hwconfig->read() & 0x01)) // joystick disable jumper
+ data = m_joy->read() & 0x1f;
break;
case 0x9f:
m_romcs = 1;
@@ -264,12 +379,24 @@ uint8_t spectrum_mprint_device::iorq_r(offs_t offset)
return data;
}
+void spectrum_mface_base_device::iorq_w(offs_t offset, uint8_t data)
+{
+ m_exp->iorq_w(offset, data);
+}
+
void spectrum_mface1_device::iorq_w(offs_t offset, uint8_t data)
{
+ switch (offset & 0xff)
+ {
+ case 0x1f:
+ m_slot->nmi_w(CLEAR_LINE);
+ break;
+ }
+
m_exp->iorq_w(offset, data);
}
-uint8_t spectrum_mface1_device::mreq_r(offs_t offset)
+uint8_t spectrum_mface_base_device::mreq_r(offs_t offset)
{
uint8_t data = 0xff;
@@ -292,7 +419,7 @@ uint8_t spectrum_mface1_device::mreq_r(offs_t offset)
return data;
}
-void spectrum_mface1_device::mreq_w(offs_t offset, uint8_t data)
+void spectrum_mface_base_device::mreq_w(offs_t offset, uint8_t data)
{
if (m_romcs)
{
@@ -308,7 +435,7 @@ void spectrum_mface1_device::mreq_w(offs_t offset, uint8_t data)
m_exp->mreq_w(offset, data);
}
-INPUT_CHANGED_MEMBER(spectrum_mface1_device::magic_button)
+INPUT_CHANGED_MEMBER(spectrum_mface_base_device::magic_button)
{
if (newval && !oldval)
{
@@ -319,3 +446,15 @@ INPUT_CHANGED_MEMBER(spectrum_mface1_device::magic_button)
m_slot->nmi_w(CLEAR_LINE);
}
}
+
+INPUT_CHANGED_MEMBER(spectrum_mface1_device::magic_button)
+{
+ if (newval && !oldval) // key released
+ {
+
+ }
+ else // key pressed
+ {
+ m_slot->nmi_w(ASSERT_LINE);
+ }
+}
diff --git a/src/devices/bus/spectrum/mface.h b/src/devices/bus/spectrum/mface.h
index bf286cf9823..9f3d89ae6dc 100644
--- a/src/devices/bus/spectrum/mface.h
+++ b/src/devices/bus/spectrum/mface.h
@@ -15,19 +15,19 @@
// TYPE DEFINITIONS
//**************************************************************************
-class spectrum_mface1_device :
+class spectrum_mface_base_device :
public device_t,
public device_spectrum_expansion_interface
{
public:
// construction/destruction
- spectrum_mface1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ spectrum_mface_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_INPUT_CHANGED_MEMBER(magic_button);
+ virtual DECLARE_INPUT_CHANGED_MEMBER(magic_button);
protected:
- spectrum_mface1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ spectrum_mface_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
@@ -35,13 +35,11 @@ protected:
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
virtual ioport_constructor device_input_ports() const override;
virtual void pre_opcode_fetch(offs_t offset) override;
virtual uint8_t mreq_r(offs_t offset) override;
virtual void mreq_w(offs_t offset, uint8_t data) 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;
@@ -52,7 +50,27 @@ protected:
int m_romcs;
};
-class spectrum_mface128_device : public spectrum_mface1_device
+class spectrum_mface1_device : public spectrum_mface_base_device
+{
+public:
+ spectrum_mface1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(magic_button) override;
+
+protected:
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_ioport m_joy;
+ required_ioport m_hwconfig;
+};
+
+class spectrum_mface128_device : public spectrum_mface_base_device
{
public:
spectrum_mface128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -64,7 +82,7 @@ protected:
virtual uint8_t iorq_r(offs_t offset) override;
};
-class spectrum_mface3_device : public spectrum_mface1_device
+class spectrum_mface3_device : public spectrum_mface_base_device
{
public:
spectrum_mface3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -76,7 +94,7 @@ protected:
virtual uint8_t iorq_r(offs_t offset) override;
};
-class spectrum_mprint_device : public spectrum_mface1_device
+class spectrum_mprint_device : public spectrum_mface_base_device
{
public:
spectrum_mprint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);