mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
ZX Spectrum Multiface One improvements (#5885)
* mface * mface improvements * use required_ioport, remove disable switch
This commit is contained in:
parent
0a83f32207
commit
4f0dd32003
@ -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_mface1_device::iorq_w(offs_t offset, uint8_t data)
|
||||
void spectrum_mface_base_device::iorq_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_exp->iorq_w(offset, data);
|
||||
}
|
||||
|
||||
uint8_t spectrum_mface1_device::mreq_r(offs_t offset)
|
||||
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_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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user