summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Nigel Barnes <Pernod70@users.noreply.github.com>2017-09-21 22:39:07 +0100
committer Nigel Barnes <Pernod70@users.noreply.github.com>2017-09-21 23:08:50 +0100
commitcdde9d681480511d164ae045111decc9f81a71af (patch)
tree2ab5a4864852695e1794fafc3aeca8bed0449db8
parent5db14d55354532e4e1e77685e98dc31fda75662c (diff)
spectrum: Added expansion slot, and devices:
- ZX Interface 1 (not working) - ZX Interface 2 - Fuller Box - Kempston Joystick Interface (moved from driver) - Didaktik Melodik - Mikro-Plus (Shadow of the Unicorn) - Protek Joystick Interface - Currah MicroSlot - Currah MicroSpeech [Thomas Busse] - Currah MicroSource spec128: Added expansion slot, and devices: - ZX Interface 1 (not working) - ZX Interface 2 - Kempston Joystick Interface (moved from driver) - Mikro-Plus (Shadow of the Unicorn) - Protek Joystick Interface - Spectrum +2 Test Software
-rw-r--r--scripts/src/bus.lua34
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/devices/bus/spectrum/exp.cpp186
-rw-r--r--src/devices/bus/spectrum/exp.h147
-rw-r--r--src/devices/bus/spectrum/fuller.cpp132
-rw-r--r--src/devices/bus/spectrum/fuller.h59
-rw-r--r--src/devices/bus/spectrum/intf1.cpp143
-rw-r--r--src/devices/bus/spectrum/intf1.h59
-rw-r--r--src/devices/bus/spectrum/intf2.cpp150
-rw-r--r--src/devices/bus/spectrum/intf2.h56
-rw-r--r--src/devices/bus/spectrum/kempjoy.cpp88
-rw-r--r--src/devices/bus/spectrum/kempjoy.h50
-rw-r--r--src/devices/bus/spectrum/melodik.cpp101
-rw-r--r--src/devices/bus/spectrum/melodik.h55
-rw-r--r--src/devices/bus/spectrum/mikroplus.cpp118
-rw-r--r--src/devices/bus/spectrum/mikroplus.h55
-rw-r--r--src/devices/bus/spectrum/plus2test.cpp84
-rw-r--r--src/devices/bus/spectrum/plus2test.h51
-rw-r--r--src/devices/bus/spectrum/protek.cpp98
-rw-r--r--src/devices/bus/spectrum/protek.h51
-rw-r--r--src/devices/bus/spectrum/uslot.cpp116
-rw-r--r--src/devices/bus/spectrum/uslot.h56
-rw-r--r--src/devices/bus/spectrum/usource.cpp99
-rw-r--r--src/devices/bus/spectrum/usource.h55
-rw-r--r--src/devices/bus/spectrum/uspeech.cpp151
-rw-r--r--src/devices/bus/spectrum/uspeech.h59
-rw-r--r--src/mame/drivers/atm.cpp10
-rw-r--r--src/mame/drivers/pentagon.cpp10
-rw-r--r--src/mame/drivers/scorpion.cpp10
-rw-r--r--src/mame/drivers/spec128.cpp61
-rw-r--r--src/mame/drivers/specpls3.cpp53
-rw-r--r--src/mame/drivers/spectrum.cpp154
-rw-r--r--src/mame/drivers/timex.cpp24
-rw-r--r--src/mame/includes/spectrum.h35
34 files changed, 2440 insertions, 171 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index 0cffcaeee67..bc95ad1eca0 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -2882,6 +2882,40 @@ end
---------------------------------------------------
--
+--@src/devices/bus/spectrum/exp.h,BUSES["SPECTRUM"] = true
+---------------------------------------------------
+
+if (BUSES["SPECTRUM"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/bus/spectrum/exp.cpp",
+ MAME_DIR .. "src/devices/bus/spectrum/exp.h",
+ MAME_DIR .. "src/devices/bus/spectrum/intf1.cpp",
+ MAME_DIR .. "src/devices/bus/spectrum/intf1.h",
+ MAME_DIR .. "src/devices/bus/spectrum/intf2.cpp",
+ MAME_DIR .. "src/devices/bus/spectrum/intf2.h",
+ MAME_DIR .. "src/devices/bus/spectrum/fuller.cpp",
+ MAME_DIR .. "src/devices/bus/spectrum/fuller.h",
+ MAME_DIR .. "src/devices/bus/spectrum/kempjoy.cpp",
+ MAME_DIR .. "src/devices/bus/spectrum/kempjoy.h",
+ MAME_DIR .. "src/devices/bus/spectrum/melodik.cpp",
+ MAME_DIR .. "src/devices/bus/spectrum/melodik.h",
+ MAME_DIR .. "src/devices/bus/spectrum/mikroplus.cpp",
+ MAME_DIR .. "src/devices/bus/spectrum/mikroplus.h",
+ MAME_DIR .. "src/devices/bus/spectrum/plus2test.cpp",
+ MAME_DIR .. "src/devices/bus/spectrum/plus2test.h",
+ MAME_DIR .. "src/devices/bus/spectrum/protek.cpp",
+ MAME_DIR .. "src/devices/bus/spectrum/protek.h",
+ MAME_DIR .. "src/devices/bus/spectrum/uslot.cpp",
+ MAME_DIR .. "src/devices/bus/spectrum/uslot.h",
+ MAME_DIR .. "src/devices/bus/spectrum/usource.cpp",
+ MAME_DIR .. "src/devices/bus/spectrum/usource.h",
+ MAME_DIR .. "src/devices/bus/spectrum/uspeech.cpp",
+ MAME_DIR .. "src/devices/bus/spectrum/uspeech.h",
+ }
+end
+
+---------------------------------------------------
+--
--@src/devices/bus/vtech/memexp/memexp.h,BUSES["VTECH_MEMEXP"] = true
---------------------------------------------------
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index fc3141afa9e..73f87e5faa1 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -719,6 +719,7 @@ BUSES["SMS_EXP"] = true
BUSES["SNES"] = true
BUSES["SNES_CTRL"] = true
BUSES["SPC1000"] = true
+BUSES["SPECTRUM"] = true
BUSES["SUNKBD"] = true
BUSES["SVI_EXPANDER"] = true
BUSES["SVI_SLOT"] = true
diff --git a/src/devices/bus/spectrum/exp.cpp b/src/devices/bus/spectrum/exp.cpp
new file mode 100644
index 00000000000..c365f3644f3
--- /dev/null
+++ b/src/devices/bus/spectrum/exp.cpp
@@ -0,0 +1,186 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ZX Spectrum Expansion Port emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "exp.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_EXPANSION_SLOT, spectrum_expansion_slot_device, "spectrum_expansion_slot", "ZX Spectrum Expansion port")
+
+
+//**************************************************************************
+// DEVICE SPECTRUM_EXPANSION CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_spectrum_expansion_interface - constructor
+//-------------------------------------------------
+
+device_spectrum_expansion_interface::device_spectrum_expansion_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig, device)
+{
+ m_slot = dynamic_cast<spectrum_expansion_slot_device *>(device.owner());
+}
+
+
+//-------------------------------------------------
+// ~device_spectrum_expansion_interface - destructor
+//-------------------------------------------------
+
+device_spectrum_expansion_interface::~device_spectrum_expansion_interface()
+{
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_expansion_slot_device - constructor
+//-------------------------------------------------
+
+spectrum_expansion_slot_device::spectrum_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SPECTRUM_EXPANSION_SLOT, tag, owner, clock),
+ device_slot_interface(mconfig, *this),
+ m_card(nullptr),
+ m_irq_handler(*this),
+ m_nmi_handler(*this)
+{
+}
+
+
+//-------------------------------------------------
+// expansion_slot_device - destructor
+//-------------------------------------------------
+
+spectrum_expansion_slot_device::~spectrum_expansion_slot_device()
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_expansion_slot_device::device_start()
+{
+ m_card = dynamic_cast<device_spectrum_expansion_interface *>(get_card_device());
+
+ // resolve callbacks
+ m_irq_handler.resolve_safe();
+ m_nmi_handler.resolve_safe();
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_expansion_slot_device::device_reset()
+{
+ if (get_card_device())
+ {
+ get_card_device()->reset();
+ }
+}
+
+//-------------------------------------------------
+// port_fe_r
+//-------------------------------------------------
+
+READ8_MEMBER(spectrum_expansion_slot_device::port_fe_r)
+{
+ if (m_card)
+ return m_card->port_fe_r(space, offset);
+ else
+ return 0xff;
+}
+
+//-------------------------------------------------
+// romcs
+//-------------------------------------------------
+
+READ_LINE_MEMBER(spectrum_expansion_slot_device::romcs)
+{
+ if (m_card)
+ return m_card->romcs();
+ else
+ return 0;
+}
+
+//-------------------------------------------------
+// mreq_r
+//-------------------------------------------------
+
+READ8_MEMBER(spectrum_expansion_slot_device::mreq_r)
+{
+ if (m_card)
+ return m_card->mreq_r(space, offset);
+ else
+ return 0xff;
+}
+
+//-------------------------------------------------
+// mreq_w
+//-------------------------------------------------
+
+WRITE8_MEMBER(spectrum_expansion_slot_device::mreq_w)
+{
+ if (m_card)
+ m_card->mreq_w(space, offset, data);
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( spectrum_expansion_devices )
+//-------------------------------------------------
+
+
+// slot devices
+#include "intf1.h"
+#include "intf2.h"
+#include "fuller.h"
+#include "kempjoy.h"
+#include "melodik.h"
+#include "mikroplus.h"
+#include "plus2test.h"
+#include "protek.h"
+#include "uslot.h"
+#include "usource.h"
+#include "uspeech.h"
+
+
+SLOT_INTERFACE_START( spectrum_expansion_devices )
+ SLOT_INTERFACE("intf1", SPECTRUM_INTF1)
+ SLOT_INTERFACE("intf2", SPECTRUM_INTF2)
+ SLOT_INTERFACE("fuller", SPECTRUM_FULLER)
+ SLOT_INTERFACE("kempjoy", SPECTRUM_KEMPJOY)
+ SLOT_INTERFACE("melodik", SPECTRUM_MELODIK)
+ SLOT_INTERFACE("mikroplus", SPECTRUM_MIKROPLUS)
+ SLOT_INTERFACE("protek", SPECTRUM_PROTEK)
+ SLOT_INTERFACE("uslot", SPECTRUM_USLOT)
+ SLOT_INTERFACE("usource", SPECTRUM_USOURCE)
+ SLOT_INTERFACE("uspeech", SPECTRUM_USPEECH)
+SLOT_INTERFACE_END
+
+SLOT_INTERFACE_START( spec128_expansion_devices )
+ SLOT_INTERFACE("intf1", SPECTRUM_INTF1)
+ SLOT_INTERFACE("intf2", SPECTRUM_INTF2)
+ SLOT_INTERFACE("kempjoy", SPECTRUM_KEMPJOY)
+ SLOT_INTERFACE("mikroplus", SPECTRUM_MIKROPLUS)
+ SLOT_INTERFACE("plus2test", SPECTRUM_PLUS2TEST)
+ SLOT_INTERFACE("protek", SPECTRUM_PROTEK)
+SLOT_INTERFACE_END
+
+SLOT_INTERFACE_START( specpls3_expansion_devices )
+SLOT_INTERFACE_END
+
diff --git a/src/devices/bus/spectrum/exp.h b/src/devices/bus/spectrum/exp.h
new file mode 100644
index 00000000000..b82707073a6
--- /dev/null
+++ b/src/devices/bus/spectrum/exp.h
@@ -0,0 +1,147 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ZX Spectrum Expansion Port emulation
+
+**********************************************************************
+
+ Pinout:
+
+ A15 1 A14
+ A13 2 A12
+ D7 3 +5v
+ ¬OE 4 NC
+ SLOT 5 SLOT
+ D0 6 0v
+ D1 7 0v
+ D2 8 ¬CK
+ D6 9 A0
+ D5 10 A1
+ D3 11 A2
+ D4 12 A3
+ ¬INT 13 NC
+ ¬NMI 14 0v
+ ¬HALT 15 ¬OE
+ ¬MREQ 16 NC
+ ¬IORQ 17 NC
+ ¬RD 18 NC
+ ¬WR 19 ¬BUSRQ
+ NC 20 ¬RESET
+ ¬WAIT 21 A7
+ +12v 22 A6
+ NC 23 A5
+ ¬M1 24 A4
+ ¬RFSH 25 ¬ROMCS
+ A8 26 ¬BUSACK
+ A10 27 A9
+ NC 28 A11
+
+**********************************************************************/
+
+#ifndef MAME_BUS_SPECTRUM_EXP_H
+#define MAME_BUS_SPECTRUM_EXP_H
+
+#pragma once
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+#define SPECTRUM_EXPANSION_SLOT_TAG "exp"
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_SPECTRUM_EXPANSION_SLOT_ADD(_tag, _slot_intf, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, SPECTRUM_EXPANSION_SLOT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
+
+#define MCFG_SPECTRUM_PASSTHRU_EXPANSION_SLOT_ADD() \
+ MCFG_SPECTRUM_EXPANSION_SLOT_ADD(SPECTRUM_EXPANSION_SLOT_TAG, spectrum_expansion_devices, nullptr) \
+ MCFG_SPECTRUM_EXPANSION_SLOT_IRQ_HANDLER(DEVWRITELINE(DEVICE_SELF_OWNER, spectrum_expansion_slot_device, irq_w)) \
+ MCFG_SPECTRUM_EXPANSION_SLOT_NMI_HANDLER(DEVWRITELINE(DEVICE_SELF_OWNER, spectrum_expansion_slot_device, nmi_w))
+
+#define MCFG_SPECTRUM_EXPANSION_SLOT_IRQ_HANDLER(_devcb) \
+ devcb = &spectrum_expansion_slot_device::set_irq_handler(*device, DEVCB_##_devcb);
+
+#define MCFG_SPECTRUM_EXPANSION_SLOT_NMI_HANDLER(_devcb) \
+ devcb = &spectrum_expansion_slot_device::set_nmi_handler(*device, DEVCB_##_devcb);
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> spectrum_expansion_slot_device
+
+class device_spectrum_expansion_interface;
+
+class spectrum_expansion_slot_device : public device_t, public device_slot_interface
+{
+public:
+ // construction/destruction
+ spectrum_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~spectrum_expansion_slot_device();
+
+ // callbacks
+ template <class Object> static devcb_base &set_irq_handler(device_t &device, Object &&cb)
+ { return downcast<spectrum_expansion_slot_device &>(device).m_irq_handler.set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> static devcb_base &set_nmi_handler(device_t &device, Object &&cb)
+ { return downcast<spectrum_expansion_slot_device &>(device).m_nmi_handler.set_callback(std::forward<Object>(cb)); }
+
+ DECLARE_READ8_MEMBER( mreq_r );
+ DECLARE_WRITE8_MEMBER( mreq_w );
+ DECLARE_READ8_MEMBER( port_fe_r );
+ DECLARE_READ_LINE_MEMBER( romcs );
+
+ DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_irq_handler(state); }
+ DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_handler(state); }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ device_spectrum_expansion_interface *m_card;
+
+private:
+ devcb_write_line m_irq_handler;
+ devcb_write_line m_nmi_handler;
+};
+
+
+// ======================> device_spectrum_expansion_interface
+
+class device_spectrum_expansion_interface : public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_spectrum_expansion_interface();
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(mreq_r) { return 0xff; }
+ virtual DECLARE_WRITE8_MEMBER(mreq_w) { }
+ virtual DECLARE_READ8_MEMBER(port_fe_r) { return 0xff; }
+ virtual DECLARE_READ_LINE_MEMBER(romcs) { return 0; }
+
+protected:
+ device_spectrum_expansion_interface(const machine_config &mconfig, device_t &device);
+
+ spectrum_expansion_slot_device *m_slot;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_EXPANSION_SLOT, spectrum_expansion_slot_device)
+
+SLOT_INTERFACE_EXTERN( spectrum_expansion_devices );
+SLOT_INTERFACE_EXTERN( spec128_expansion_devices );
+SLOT_INTERFACE_EXTERN( specpls3_expansion_devices );
+
+
+#endif // MAME_BUS_SPECTRUM_EXP_H
diff --git a/src/devices/bus/spectrum/fuller.cpp b/src/devices/bus/spectrum/fuller.cpp
new file mode 100644
index 00000000000..d2c9bb6ff21
--- /dev/null
+++ b/src/devices/bus/spectrum/fuller.cpp
@@ -0,0 +1,132 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Fuller Box Games Unit
+
+**********************************************************************/
+
+#include "emu.h"
+#include "fuller.h"
+#include "speaker.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_FULLER, spectrum_fuller_device, "spectrum_fuller", "Fuller Box")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( fuller )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( fuller )
+ PORT_START("JOY")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_BUTTON1)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor spectrum_fuller_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( fuller );
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+MACHINE_CONFIG_MEMBER(spectrum_fuller_device::device_add_mconfig)
+ /* sound hardware */
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_ADD("ay8912", AY8912, XTAL_3_579545MHz / 2) // unverified clock
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+
+ /* passthru */
+ MCFG_SPECTRUM_PASSTHRU_EXPANSION_SLOT_ADD()
+MACHINE_CONFIG_END
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_fuller_device - constructor
+//-------------------------------------------------
+
+spectrum_fuller_device::spectrum_fuller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_FULLER, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_exp(*this, "exp")
+ , m_psg(*this, "ay8912")
+ , m_joy(*this, "JOY")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_fuller_device::device_start()
+{
+ address_space& spaceio = machine().device("maincpu")->memory().space(AS_IO);
+ m_slot = dynamic_cast<spectrum_expansion_slot_device *>(owner());
+
+ spaceio.install_write_handler(0x3f, 0x3f, 0, 0xff00, 0, write8_delegate(FUNC(ay8910_device::address_w), (ay8910_device*)m_psg));
+ spaceio.install_readwrite_handler(0x5f, 0x5f, 0, 0xff00, 0, read8_delegate(FUNC(ay8910_device::data_r), (ay8910_device*)m_psg), write8_delegate(FUNC(ay8910_device::data_w), (ay8910_device*)m_psg));
+ spaceio.install_read_handler(0x7f, 0x7f, 0, 0xff00, 0, read8_delegate(FUNC(spectrum_fuller_device::joystick_r), this));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_fuller_device::device_reset()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+READ8_MEMBER(spectrum_fuller_device::joystick_r)
+{
+ return m_joy->read() | (0xff ^ 0x8f);
+}
+
+READ_LINE_MEMBER(spectrum_fuller_device::romcs)
+{
+ return m_exp->romcs();
+}
+
+READ8_MEMBER(spectrum_fuller_device::mreq_r)
+{
+ return m_exp->mreq_r(space, offset);
+}
+
+WRITE8_MEMBER(spectrum_fuller_device::mreq_w)
+{
+ if (m_exp->romcs())
+ m_exp->mreq_w(space, offset, data);
+}
+
+READ8_MEMBER(spectrum_fuller_device::port_fe_r)
+{
+ uint8_t data = 0xff;
+
+ if (m_exp->romcs())
+ data &= m_exp->port_fe_r(space, offset);
+
+ return data;
+} \ No newline at end of file
diff --git a/src/devices/bus/spectrum/fuller.h b/src/devices/bus/spectrum/fuller.h
new file mode 100644
index 00000000000..b0431121424
--- /dev/null
+++ b/src/devices/bus/spectrum/fuller.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Fuller Box Games Unit
+
+**********************************************************************/
+
+#ifndef MAME_BUS_SPECTRUM_FULLER_H
+#define MAME_BUS_SPECTRUM_FULLER_H
+
+#pragma once
+
+
+#include "exp.h"
+#include "sound/ay8910.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> spectrum_fuller_device
+
+class spectrum_fuller_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_fuller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual DECLARE_READ8_MEMBER(mreq_r) override;
+ virtual DECLARE_WRITE8_MEMBER(mreq_w) override;
+ virtual DECLARE_READ8_MEMBER(port_fe_r) override;
+ virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+
+private:
+ DECLARE_READ8_MEMBER(joystick_r);
+
+ required_device<spectrum_expansion_slot_device> m_exp;
+ required_device<ay8910_device> m_psg;
+ required_ioport m_joy;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_FULLER, spectrum_fuller_device)
+
+
+#endif // MAME_BUS_SPECTRUM_FULLER_H
diff --git a/src/devices/bus/spectrum/intf1.cpp b/src/devices/bus/spectrum/intf1.cpp
new file mode 100644
index 00000000000..e0d627dce70
--- /dev/null
+++ b/src/devices/bus/spectrum/intf1.cpp
@@ -0,0 +1,143 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ZX Interface 1
+
+ The ZX Interface 1 combines the three functions of microdrive
+ controller, local area network and RS232 interface.
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "intf1.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_INTF1, spectrum_intf1_device, "spectrum_intf1", "ZX Interface 1")
+
+
+//-------------------------------------------------
+// MACHINE_DRIVER( intf1 )
+//-------------------------------------------------
+
+ROM_START( intf1 )
+ ROM_REGION( 0x2000, "rom", 0 )
+ ROM_DEFAULT_BIOS("v2")
+ ROM_SYSTEM_BIOS(0, "v1", "v1")
+ ROMX_LOAD("if1-1.rom", 0x0000, 0x2000, CRC(e72a12ae) SHA1(4ffd9ed9c00cdc6f92ce69fdd8b618ef1203f48e), ROM_BIOS(1))
+
+ ROM_SYSTEM_BIOS(1, "v2", "v2")
+ ROMX_LOAD("if1-2.rom", 0x0000, 0x2000, CRC(bb66dd1e) SHA1(5cfb6bca4177c45fefd571734576b55e3a127c08), ROM_BIOS(2))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+MACHINE_CONFIG_MEMBER( spectrum_intf1_device::device_add_mconfig )
+ /* rs232 */
+ MCFG_RS232_PORT_ADD("rs232", default_rs232_devices, nullptr)
+
+ /* microdrive */
+ MCFG_MICRODRIVE_ADD("mdv1")
+ MCFG_MICRODRIVE_COMMS_OUT_CALLBACK(DEVWRITELINE("mdv2", microdrive_image_device, comms_in_w))
+ MCFG_MICRODRIVE_ADD("mdv2")
+
+ /* passthru */
+ MCFG_SPECTRUM_PASSTHRU_EXPANSION_SLOT_ADD()
+MACHINE_CONFIG_END
+
+const tiny_rom_entry *spectrum_intf1_device::device_rom_region() const
+{
+ return ROM_NAME( intf1 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_intf1_device - constructor
+//-------------------------------------------------
+
+spectrum_intf1_device::spectrum_intf1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_INTF1, tag, owner, clock),
+ device_spectrum_expansion_interface(mconfig, *this),
+ m_exp(*this, "exp"),
+ m_rs232(*this, "rs232"),
+ m_mdv1(*this, "mdv1"),
+ m_mdv2(*this, "mdv2"),
+ m_rom(*this, "rom")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_intf1_device::device_start()
+{
+ m_slot = dynamic_cast<spectrum_expansion_slot_device *>(owner());
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_intf1_device::device_reset()
+{
+ m_romcs = 0;
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+READ_LINE_MEMBER(spectrum_intf1_device::romcs)
+{
+ return m_romcs | m_exp->romcs();
+}
+
+READ8_MEMBER(spectrum_intf1_device::mreq_r)
+{
+ uint8_t temp;
+ uint8_t data = 0xff;
+
+ if (!machine().side_effect_disabled())
+ {
+ if (offset == 0x0008 || offset == 0x1708)
+ m_romcs = 1;
+ if (offset == 0x0700)
+ m_romcs = 0;
+ }
+
+ temp = m_exp->mreq_r(space, offset);
+ if (m_exp->romcs())
+ data &= temp;
+
+ if (m_romcs)
+ data &= m_rom->base()[offset & 0x1fff];
+
+ return data;
+}
+
+WRITE8_MEMBER(spectrum_intf1_device::mreq_w)
+{
+ if (m_exp->romcs())
+ m_exp->mreq_w(space, offset, data);
+}
+
+READ8_MEMBER(spectrum_intf1_device::port_fe_r)
+{
+ uint8_t data = 0xff;
+
+ if (m_exp->romcs())
+ data &= m_exp->port_fe_r(space, offset);
+
+ return data;
+}
diff --git a/src/devices/bus/spectrum/intf1.h b/src/devices/bus/spectrum/intf1.h
new file mode 100644
index 00000000000..5a21cd9927d
--- /dev/null
+++ b/src/devices/bus/spectrum/intf1.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ZX Interface 1
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_SPECTRUM_INTF1_H
+#define MAME_BUS_SPECTRUM_INTF1_H
+
+#include "exp.h"
+#include "bus/rs232/rs232.h"
+#include "machine/microdrv.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class spectrum_intf1_device:
+ public device_t,
+ public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_intf1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK | feature::LAN; }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual DECLARE_READ8_MEMBER(mreq_r) override;
+ virtual DECLARE_WRITE8_MEMBER(mreq_w) override;
+ virtual DECLARE_READ8_MEMBER(port_fe_r) override;
+ virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+
+private:
+ required_device<spectrum_expansion_slot_device> m_exp;
+ required_device<rs232_port_device> m_rs232;
+ required_device<microdrive_image_device> m_mdv1;
+ required_device<microdrive_image_device> m_mdv2;
+ required_memory_region m_rom;
+
+ int m_romcs;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_INTF1, spectrum_intf1_device)
+
+
+#endif /* MAME_BUS_SPECTRUM_INTF1_H */
diff --git a/src/devices/bus/spectrum/intf2.cpp b/src/devices/bus/spectrum/intf2.cpp
new file mode 100644
index 00000000000..1ec809a52cd
--- /dev/null
+++ b/src/devices/bus/spectrum/intf2.cpp
@@ -0,0 +1,150 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ZX Interface 2
+
+ The Sinclair ZX Interface 2 allows you to connect two joysticks
+ and a ROM software cartridge to your ZX Spectrum.
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "intf2.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_INTF2, spectrum_intf2_device, "spectrum_intf2", "ZX Interface 2")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( intf2 )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( intf2 )
+ PORT_START("LINE3") /* 0xF7FE */
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_X_LEFT_SWITCH)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_X_RIGHT_SWITCH)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_Y_UP_SWITCH)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2) PORT_CODE(JOYCODE_BUTTON1)
+
+ PORT_START("LINE4") /* 0xEFFE */
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(1)
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor spectrum_intf2_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( intf2 );
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+MACHINE_CONFIG_MEMBER( spectrum_intf2_device::device_add_mconfig )
+ /* cartridge */
+ MCFG_GENERIC_CARTSLOT_ADD("cartslot", generic_plain_slot, "spectrum_cart")
+ MCFG_GENERIC_EXTENSIONS("bin,rom")
+ MCFG_GENERIC_LOAD(spectrum_intf2_device, spectrum_cart)
+
+ MCFG_SOFTWARE_LIST_ADD("cart_list", "spectrum_cart")
+MACHINE_CONFIG_END
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_intf2_device - constructor
+//-------------------------------------------------
+
+spectrum_intf2_device::spectrum_intf2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_INTF2, tag, owner, clock),
+ device_spectrum_expansion_interface(mconfig, *this),
+ m_cart(*this, "cartslot"),
+ m_exp_line3(*this, "LINE3"),
+ m_exp_line4(*this, "LINE4")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_intf2_device::device_start()
+{
+ m_slot = dynamic_cast<spectrum_expansion_slot_device *>(owner());
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_intf2_device::device_reset()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+DEVICE_IMAGE_LOAD_MEMBER(spectrum_intf2_device, spectrum_cart)
+{
+ uint32_t size = m_cart->common_get_size("rom");
+
+ if (size != 0x4000)
+ {
+ image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size");
+ return image_init_result::FAIL;
+ }
+
+ m_cart->rom_alloc(size, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
+ m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom");
+
+ return image_init_result::PASS;
+}
+
+READ_LINE_MEMBER(spectrum_intf2_device::romcs)
+{
+ if (m_cart && m_cart->exists())
+ return 1;
+ else
+ return 0;
+}
+
+READ8_MEMBER(spectrum_intf2_device::mreq_r)
+{
+ if (m_cart && m_cart->exists())
+ return m_cart->get_rom_base()[offset & 0x3fff];
+ else
+ return 0xff;
+}
+
+READ8_MEMBER(spectrum_intf2_device::port_fe_r)
+{
+ uint8_t data = 0xff;
+
+ uint8_t lines = offset >> 8;
+
+ if ((lines & 8) == 0)
+ data = m_exp_line3->read() | (0xff ^ 0x1f);
+
+ if ((lines & 16) == 0)
+ data = m_exp_line4->read() | (0xff ^ 0x1f);
+
+ return data;
+}
diff --git a/src/devices/bus/spectrum/intf2.h b/src/devices/bus/spectrum/intf2.h
new file mode 100644
index 00000000000..54316ef88c5
--- /dev/null
+++ b/src/devices/bus/spectrum/intf2.h
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ZX Interface 2
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_SPECTRUM_INTF2_H
+#define MAME_BUS_SPECTRUM_INTF2_H
+
+#include "exp.h"
+#include "softlist.h"
+#include "bus/generic/slot.h"
+#include "bus/generic/carts.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class spectrum_intf2_device:
+ public device_t,
+ public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_intf2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual DECLARE_READ8_MEMBER(mreq_r) override;
+ virtual DECLARE_READ8_MEMBER(port_fe_r) override;
+
+private:
+ image_init_result load_cart(device_image_interface &image, generic_slot_device *slot);
+ DECLARE_DEVICE_IMAGE_LOAD_MEMBER(spectrum_cart);
+
+ required_device<generic_slot_device> m_cart;
+ required_ioport m_exp_line3;
+ required_ioport m_exp_line4;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_INTF2, spectrum_intf2_device)
+
+
+#endif /* MAME_BUS_SPECTRUM_INTF2_H */
diff --git a/src/devices/bus/spectrum/kempjoy.cpp b/src/devices/bus/spectrum/kempjoy.cpp
new file mode 100644
index 00000000000..4f13fdc482f
--- /dev/null
+++ b/src/devices/bus/spectrum/kempjoy.cpp
@@ -0,0 +1,88 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Kempston Joystick Interface
+
+**********************************************************************/
+
+#include "emu.h"
+#include "kempjoy.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_KEMPJOY, spectrum_kempjoy_device, "spectrum_kempjoy", "Kempston Joystick Interface")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( kempjoy )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( kempjoy )
+ 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_kempjoy_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( kempjoy );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_kempjoy_device - constructor
+//-------------------------------------------------
+
+spectrum_kempjoy_device::spectrum_kempjoy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_KEMPJOY, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_joy(*this, "JOY")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_kempjoy_device::device_start()
+{
+ address_space& spaceio = machine().device("maincpu")->memory().space(AS_IO);
+ m_slot = dynamic_cast<spectrum_expansion_slot_device *>(owner());
+
+ spaceio.install_read_handler(0x1f, 0x1f, 0, 0xff00, 0, read8_delegate(FUNC(spectrum_kempjoy_device::joystick_r), this));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_kempjoy_device::device_reset()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+READ8_MEMBER(spectrum_kempjoy_device::joystick_r)
+{
+ return m_joy->read() & 0x1f;
+}
diff --git a/src/devices/bus/spectrum/kempjoy.h b/src/devices/bus/spectrum/kempjoy.h
new file mode 100644
index 00000000000..555fb67643a
--- /dev/null
+++ b/src/devices/bus/spectrum/kempjoy.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Kempston Joystick Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_SPECTRUM_KEMPJOY_H
+#define MAME_BUS_SPECTRUM_KEMPJOY_H
+
+#pragma once
+
+
+#include "exp.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> spectrum_kempjoy_device
+
+class spectrum_kempjoy_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_kempjoy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+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;
+
+private:
+ DECLARE_READ8_MEMBER(joystick_r);
+
+ required_ioport m_joy;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_KEMPJOY, spectrum_kempjoy_device)
+
+
+#endif // MAME_BUS_SPECTRUM_KEMPJOY_H
diff --git a/src/devices/bus/spectrum/melodik.cpp b/src/devices/bus/spectrum/melodik.cpp
new file mode 100644
index 00000000000..5f7481b636a
--- /dev/null
+++ b/src/devices/bus/spectrum/melodik.cpp
@@ -0,0 +1,101 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Didaktik Melodik
+
+**********************************************************************/
+
+#include "emu.h"
+#include "melodik.h"
+#include "speaker.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_MELODIK, spectrum_melodik_device, "spectrum_melodik", "Didaktik Melodik")
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+MACHINE_CONFIG_MEMBER(spectrum_melodik_device::device_add_mconfig)
+ /* sound hardware */
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_ADD("ay8912", AY8912, XTAL_3_579545MHz / 2)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+
+ /* passthru */
+ MCFG_SPECTRUM_PASSTHRU_EXPANSION_SLOT_ADD()
+MACHINE_CONFIG_END
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_melodik_device - constructor
+//-------------------------------------------------
+
+spectrum_melodik_device::spectrum_melodik_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_MELODIK, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_exp(*this, "exp")
+ , m_psg(*this, "ay8912")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_melodik_device::device_start()
+{
+ address_space& spaceio = machine().device("maincpu")->memory().space(AS_IO);
+ m_slot = dynamic_cast<spectrum_expansion_slot_device *>(owner());
+
+ spaceio.install_write_handler(0x8000, 0x8000, 0, 0x3ffd, 0, write8_delegate(FUNC(ay8910_device::address_w), (ay8910_device*)m_psg));
+ spaceio.install_readwrite_handler(0xc000, 0xc000, 0, 0x3ffd, 0, read8_delegate(FUNC(ay8910_device::data_r), (ay8910_device*)m_psg), write8_delegate(FUNC(ay8910_device::data_w), (ay8910_device*)m_psg));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_melodik_device::device_reset()
+{
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+READ_LINE_MEMBER(spectrum_melodik_device::romcs)
+{
+ return m_exp->romcs();
+}
+
+READ8_MEMBER(spectrum_melodik_device::mreq_r)
+{
+ return m_exp->mreq_r(space, offset);
+}
+
+WRITE8_MEMBER(spectrum_melodik_device::mreq_w)
+{
+ if (m_exp->romcs())
+ m_exp->mreq_w(space, offset, data);
+}
+
+READ8_MEMBER(spectrum_melodik_device::port_fe_r)
+{
+ uint8_t data = 0xff;
+
+ if (m_exp->romcs())
+ data &= m_exp->port_fe_r(space, offset);
+
+ return data;
+} \ No newline at end of file
diff --git a/src/devices/bus/spectrum/melodik.h b/src/devices/bus/spectrum/melodik.h
new file mode 100644
index 00000000000..2dc3c547836
--- /dev/null
+++ b/src/devices/bus/spectrum/melodik.h
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Didaktik Melodik
+
+**********************************************************************/
+
+#ifndef MAME_BUS_SPECTRUM_MELODIK_H
+#define MAME_BUS_SPECTRUM_MELODIK_H
+
+#pragma once
+
+
+#include "exp.h"
+#include "sound/ay8910.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> spectrum_melodik_device
+
+class spectrum_melodik_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_melodik_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual DECLARE_READ8_MEMBER(mreq_r) override;
+ virtual DECLARE_WRITE8_MEMBER(mreq_w) override;
+ virtual DECLARE_READ8_MEMBER(port_fe_r) override;
+ virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+
+private:
+ required_device<spectrum_expansion_slot_device> m_exp;
+ required_device<ay8910_device> m_psg;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_MELODIK, spectrum_melodik_device)
+
+
+#endif // MAME_BUS_SPECTRUM_MELODIK_H
diff --git a/src/devices/bus/spectrum/mikroplus.cpp b/src/devices/bus/spectrum/mikroplus.cpp
new file mode 100644
index 00000000000..6a2342d6f66
--- /dev/null
+++ b/src/devices/bus/spectrum/mikroplus.cpp
@@ -0,0 +1,118 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Mikro-Plus - Shadow of the Unicorn
+
+**********************************************************************/
+
+#include "emu.h"
+#include "mikroplus.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_MIKROPLUS, spectrum_mikroplus_device, "spectrum_mikroplus", "Mikro-Plus - Shadow of the Unicorn")
+
+
+//-------------------------------------------------
+// ROM( mikroplus )
+//-------------------------------------------------
+
+ROM_START( mikroplus )
+ ROM_REGION(0x4000, "rom", 0)
+ ROM_LOAD("ShadowOfTheUnicorn.rom", 0x0000, 0x4000, CRC(7085a0fd) SHA1(66cc823587b520af9636eed7a342d69d3dd15123))
+ROM_END
+
+
+//-------------------------------------------------
+// INPUT_PORTS( mikroplus )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( mikroplus )
+ PORT_START("JOY")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor spectrum_mikroplus_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( mikroplus );
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *spectrum_mikroplus_device::device_rom_region() const
+{
+ return ROM_NAME( mikroplus );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_mikroplus_device - constructor
+//-------------------------------------------------
+
+spectrum_mikroplus_device::spectrum_mikroplus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_MIKROPLUS, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_joy(*this, "JOY")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_mikroplus_device::device_start()
+{
+ address_space& spaceio = machine().device("maincpu")->memory().space(AS_IO);
+ m_slot = dynamic_cast<spectrum_expansion_slot_device *>(owner());
+
+ spaceio.install_read_handler(0xdf, 0xdf, 0, 0xff00, 0, read8_delegate(FUNC(spectrum_mikroplus_device::joystick_r), this));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_mikroplus_device::device_reset()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+READ8_MEMBER(spectrum_mikroplus_device::joystick_r)
+{
+ return m_joy->read() | (0xff ^ 0x1f);
+}
+
+READ_LINE_MEMBER(spectrum_mikroplus_device::romcs)
+{
+ return 1;
+}
+
+READ8_MEMBER(spectrum_mikroplus_device::mreq_r)
+{
+ return m_rom->base()[offset & 0x3fff];
+}
diff --git a/src/devices/bus/spectrum/mikroplus.h b/src/devices/bus/spectrum/mikroplus.h
new file mode 100644
index 00000000000..927cff5f56a
--- /dev/null
+++ b/src/devices/bus/spectrum/mikroplus.h
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Mikro-Plus Joystick Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_SPECTRUM_MIKROPLUS_H
+#define MAME_BUS_SPECTRUM_MIKROPLUS_H
+
+#pragma once
+
+
+#include "exp.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> spectrum_mikroplus_device
+
+class spectrum_mikroplus_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_mikroplus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual DECLARE_READ8_MEMBER(mreq_r) override;
+
+private:
+ DECLARE_READ8_MEMBER(joystick_r);
+
+ required_memory_region m_rom;
+ required_ioport m_joy;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_MIKROPLUS, spectrum_mikroplus_device)
+
+
+#endif // MAME_BUS_SPECTRUM_MIKROPLUS_H
diff --git a/src/devices/bus/spectrum/plus2test.cpp b/src/devices/bus/spectrum/plus2test.cpp
new file mode 100644
index 00000000000..2255fb86611
--- /dev/null
+++ b/src/devices/bus/spectrum/plus2test.cpp
@@ -0,0 +1,84 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Spectrum +2 Test Software
+
+**********************************************************************/
+
+#include "emu.h"
+#include "plus2test.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_PLUS2TEST, spectrum_plus2test_device, "spectrum_plus2test", "Spectrum +2 Test Software")
+
+
+//-------------------------------------------------
+// ROM( plus2test )
+//-------------------------------------------------
+
+ROM_START( plus2test )
+ ROM_REGION(0x4000, "rom", 0)
+ ROM_LOAD("plus2test.rom", 0x0000, 0x2000, CRC(6bbe1079) SHA1(2ed54f8ccf1ef26045bb409bb86c859ee23e83d1))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *spectrum_plus2test_device::device_rom_region() const
+{
+ return ROM_NAME( plus2test );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_plus2test_device - constructor
+//-------------------------------------------------
+
+spectrum_plus2test_device::spectrum_plus2test_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_PLUS2TEST, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_plus2test_device::device_start()
+{
+ m_slot = dynamic_cast<spectrum_expansion_slot_device *>(owner());
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_plus2test_device::device_reset()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+READ_LINE_MEMBER(spectrum_plus2test_device::romcs)
+{
+ return 1;
+}
+
+READ8_MEMBER(spectrum_plus2test_device::mreq_r)
+{
+ return m_rom->base()[offset & 0x3fff];
+} \ No newline at end of file
diff --git a/src/devices/bus/spectrum/plus2test.h b/src/devices/bus/spectrum/plus2test.h
new file mode 100644
index 00000000000..22158c7efc3
--- /dev/null
+++ b/src/devices/bus/spectrum/plus2test.h
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Spectrum +2 Test Software
+
+**********************************************************************/
+
+#ifndef MAME_BUS_SPECTRUM_PLUS2TEST_H
+#define MAME_BUS_SPECTRUM_PLUS2TEST_H
+
+#pragma once
+
+
+#include "exp.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> spectrum_plus2test_device
+
+class spectrum_plus2test_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_plus2test_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual DECLARE_READ8_MEMBER(mreq_r) override;
+
+private:
+ required_memory_region m_rom;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_PLUS2TEST, spectrum_plus2test_device)
+
+
+#endif // MAME_BUS_SPECTRUM_PLUS2TEST_H
diff --git a/src/devices/bus/spectrum/protek.cpp b/src/devices/bus/spectrum/protek.cpp
new file mode 100644
index 00000000000..9f00d61fcbc
--- /dev/null
+++ b/src/devices/bus/spectrum/protek.cpp
@@ -0,0 +1,98 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Protek Joystick Interface
+
+**********************************************************************/
+
+#include "emu.h"
+#include "protek.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_PROTEK, spectrum_protek_device, "spectrum_protek", "Protek Joystick Interface")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( protek )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( protek )
+ PORT_START("LINE3") /* 0xF7FE */
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY
+
+ PORT_START("LINE4") /* 0xEFFE */
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor spectrum_protek_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( protek );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_protek_device - constructor
+//-------------------------------------------------
+
+spectrum_protek_device::spectrum_protek_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_PROTEK, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_exp_line3(*this, "LINE3")
+ , m_exp_line4(*this, "LINE4")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_protek_device::device_start()
+{
+ m_slot = dynamic_cast<spectrum_expansion_slot_device *>(owner());
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_protek_device::device_reset()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+READ8_MEMBER(spectrum_protek_device::port_fe_r)
+{
+ uint8_t data = 0xff;
+
+ uint8_t lines = offset >> 8;
+
+ if ((lines & 8) == 0)
+ data = m_exp_line3->read() | (0xff ^ 0x10);
+
+ if ((lines & 16) == 0)
+ data = m_exp_line4->read() | (0xff ^ 0x1d);
+
+ return data;
+}
diff --git a/src/devices/bus/spectrum/protek.h b/src/devices/bus/spectrum/protek.h
new file mode 100644
index 00000000000..f215250ecbd
--- /dev/null
+++ b/src/devices/bus/spectrum/protek.h
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Protek Joystick Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_SPECTRUM_PROTEK_H
+#define MAME_BUS_SPECTRUM_PROTEK_H
+
+#pragma once
+
+
+#include "exp.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> spectrum_protek_device
+
+class spectrum_protek_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_protek_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+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 DECLARE_READ8_MEMBER(port_fe_r) override;
+
+private:
+ required_ioport m_exp_line3;
+ required_ioport m_exp_line4;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_PROTEK, spectrum_protek_device)
+
+
+#endif // MAME_BUS_SPECTRUM_PROTEK_H
diff --git a/src/devices/bus/spectrum/uslot.cpp b/src/devices/bus/spectrum/uslot.cpp
new file mode 100644
index 00000000000..315f768669e
--- /dev/null
+++ b/src/devices/bus/spectrum/uslot.cpp
@@ -0,0 +1,116 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Currah MicroSlot
+
+**********************************************************************/
+
+#include "emu.h"
+#include "uslot.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_USLOT, spectrum_uslot_device, "spectrum_uslot", "Spectrum Currah \xC2\xB5Slot")
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+MACHINE_CONFIG_MEMBER(spectrum_uslot_device::device_add_mconfig)
+ /* passthru */
+ MCFG_SPECTRUM_EXPANSION_SLOT_ADD("exp1", spectrum_expansion_devices, nullptr)
+ MCFG_SPECTRUM_EXPANSION_SLOT_IRQ_HANDLER(DEVWRITELINE(DEVICE_SELF_OWNER, spectrum_expansion_slot_device, irq_w))
+ MCFG_SPECTRUM_EXPANSION_SLOT_NMI_HANDLER(DEVWRITELINE(DEVICE_SELF_OWNER, spectrum_expansion_slot_device, nmi_w))
+
+ MCFG_SPECTRUM_EXPANSION_SLOT_ADD("exp2", spectrum_expansion_devices, nullptr)
+ MCFG_SPECTRUM_EXPANSION_SLOT_IRQ_HANDLER(DEVWRITELINE(DEVICE_SELF_OWNER, spectrum_expansion_slot_device, irq_w))
+ MCFG_SPECTRUM_EXPANSION_SLOT_NMI_HANDLER(DEVWRITELINE(DEVICE_SELF_OWNER, spectrum_expansion_slot_device, nmi_w))
+MACHINE_CONFIG_END
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_uslot_device - constructor
+//-------------------------------------------------
+
+spectrum_uslot_device::spectrum_uslot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_USLOT, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_exp1(*this, "exp1")
+ , m_exp2(*this, "exp2")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_uslot_device::device_start()
+{
+ m_slot = dynamic_cast<spectrum_expansion_slot_device *>(owner());
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_uslot_device::device_reset()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+READ_LINE_MEMBER(spectrum_uslot_device::romcs)
+{
+ return m_exp1->romcs() | m_exp2->romcs();
+}
+
+
+READ8_MEMBER(spectrum_uslot_device::mreq_r)
+{
+ uint8_t temp;
+ uint8_t data = 0xff;
+
+ temp = m_exp1->mreq_r(space, offset);
+ if (m_exp1->romcs())
+ data &= temp;
+
+ temp = m_exp2->mreq_r(space, offset);
+ if (m_exp2->romcs())
+ data &= temp;
+
+ return data;
+}
+
+WRITE8_MEMBER(spectrum_uslot_device::mreq_w)
+{
+ if (m_exp1->romcs())
+ m_exp1->mreq_w(space, offset, data);
+
+ if (m_exp2->romcs())
+ m_exp2->mreq_w(space, offset, data);
+}
+
+READ8_MEMBER(spectrum_uslot_device::port_fe_r)
+{
+ uint8_t data = 0xff;
+
+ if (m_exp1->romcs())
+ data &= m_exp1->port_fe_r(space, offset);
+
+ if (m_exp2->romcs())
+ data &= m_exp2->port_fe_r(space, offset);
+
+ return data;
+} \ No newline at end of file
diff --git a/src/devices/bus/spectrum/uslot.h b/src/devices/bus/spectrum/uslot.h
new file mode 100644
index 00000000000..0a3ccc70701
--- /dev/null
+++ b/src/devices/bus/spectrum/uslot.h
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Currah MicroSlot
+
+**********************************************************************/
+
+#ifndef MAME_BUS_SPECTRUM_USLOT_H
+#define MAME_BUS_SPECTRUM_USLOT_H
+
+#pragma once
+
+
+#include "exp.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> spectrum_uslot_device
+
+class spectrum_uslot_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_uslot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual DECLARE_READ8_MEMBER(mreq_r) override;
+ virtual DECLARE_WRITE8_MEMBER(mreq_w) override;
+ virtual DECLARE_READ8_MEMBER(port_fe_r) override;
+ virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+
+private:
+ required_device<spectrum_expansion_slot_device> m_exp1;
+ required_device<spectrum_expansion_slot_device> m_exp2;
+
+ int m_romcs;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_USLOT, spectrum_uslot_device)
+
+
+#endif // MAME_BUS_SPECTRUM_USLOT_H
diff --git a/src/devices/bus/spectrum/usource.cpp b/src/devices/bus/spectrum/usource.cpp
new file mode 100644
index 00000000000..b138ce97c0b
--- /dev/null
+++ b/src/devices/bus/spectrum/usource.cpp
@@ -0,0 +1,99 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Spectrum Currah MicroSource emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "usource.h"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_USOURCE, spectrum_usource_device, "spectrum_usource", "Spectrum Currah \xC2\xB5Source")
+
+
+//-------------------------------------------------
+// ROM( usource )
+//-------------------------------------------------
+
+ROM_START( usource )
+ ROM_REGION(0x2000, "rom", 0)
+ ROM_LOAD("microsource.rom", 0x0000, 0x2000, CRC(8e9b67d0) SHA1(fae53678a85ba503b77ed2d877de2635b284eef1))
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *spectrum_usource_device::device_rom_region() const
+{
+ return ROM_NAME( usource );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_usource_device - constructor
+//-------------------------------------------------
+
+spectrum_usource_device::spectrum_usource_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SPECTRUM_USOURCE, tag, owner, clock),
+ device_spectrum_expansion_interface(mconfig, *this),
+ m_rom(*this, "rom")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_usource_device::device_start()
+{
+ m_slot = dynamic_cast<spectrum_expansion_slot_device *>(owner());
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_usource_device::device_reset()
+{
+ m_romcs = 0;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+READ_LINE_MEMBER(spectrum_usource_device::romcs)
+{
+ return m_romcs;
+}
+
+
+READ8_MEMBER(spectrum_usource_device::mreq_r)
+{
+ uint8_t data;
+
+ if (!machine().side_effect_disabled() && (offset == 0x2bae))
+ {
+ m_romcs = !m_romcs;
+ }
+
+ data = m_rom->base()[offset & 0x1fff];
+
+ return data;
+}
diff --git a/src/devices/bus/spectrum/usource.h b/src/devices/bus/spectrum/usource.h
new file mode 100644
index 00000000000..607cf0737a6
--- /dev/null
+++ b/src/devices/bus/spectrum/usource.h
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Spectrum Currah MicroSource emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_SPECTRUM_USOURCE_H
+#define MAME_BUS_SPECTRUM_USOURCE_H
+
+#pragma once
+
+
+#include "exp.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> spectrum_usource_device
+
+class spectrum_usource_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_usource_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual DECLARE_READ8_MEMBER(mreq_r) override;
+
+private:
+ required_memory_region m_rom;
+
+ int m_romcs;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_USOURCE, spectrum_usource_device)
+
+
+#endif // MAME_BUS_SPECTRUM_USOURCE_H
diff --git a/src/devices/bus/spectrum/uspeech.cpp b/src/devices/bus/spectrum/uspeech.cpp
new file mode 100644
index 00000000000..03c1eeb3379
--- /dev/null
+++ b/src/devices/bus/spectrum/uspeech.cpp
@@ -0,0 +1,151 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes,Thomas Busse
+/**********************************************************************
+
+ Spectrum Currah MicroSpeech emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "uspeech.h"
+#include "speaker.h"
+
+
+
+//**************************************************************************
+// MACROS/CONSTANTS
+//**************************************************************************
+
+#define SP0256_TAG "sp0256"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_USPEECH, spectrum_uspeech_device, "spectrum_uspeech", "Spectrum Currah \xC2\xB5Speech")
+
+
+//-------------------------------------------------
+// ROM( uspeech )
+//-------------------------------------------------
+
+ROM_START( uspeech )
+ ROM_REGION(0x0800, "rom", 0)
+ ROM_LOAD("currah.rom", 0x0000, 0x0800, CRC(ce7cf52e) SHA1(90dbba5afbf07949df9cbdcb0a8ec0b106340422))
+
+ ROM_REGION(0x10000, SP0256_TAG, 0)
+ ROM_LOAD( "sp0256a-al2.bin", 0x1000, 0x0800, CRC(b504ac15) SHA1(e60fcb5fa16ff3f3b69d36c7a6e955744d3feafc) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *spectrum_uspeech_device::device_rom_region() const
+{
+ return ROM_NAME( uspeech );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+MACHINE_CONFIG_MEMBER( spectrum_uspeech_device::device_add_mconfig )
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SOUND_ADD(SP0256_TAG, SP0256, XTAL_14MHz / 4)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+MACHINE_CONFIG_END
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_uspeech_device - constructor
+//-------------------------------------------------
+
+spectrum_uspeech_device::spectrum_uspeech_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SPECTRUM_USPEECH, tag, owner, clock),
+ device_spectrum_expansion_interface(mconfig, *this),
+ m_nsp(*this, SP0256_TAG),
+ m_rom(*this, "rom")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_uspeech_device::device_start()
+{
+ m_slot = dynamic_cast<spectrum_expansion_slot_device *>(owner());
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_uspeech_device::device_reset()
+{
+ m_romcs = 0;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+READ_LINE_MEMBER(spectrum_uspeech_device::romcs)
+{
+ return m_romcs;
+}
+
+
+READ8_MEMBER(spectrum_uspeech_device::mreq_r)
+{
+ uint8_t data;
+
+ if (!machine().side_effect_disabled() && (offset == 0x38))
+ {
+ m_romcs = !m_romcs;
+ }
+
+ switch (offset)
+ {
+ case 0x1000:
+ data = !m_nsp->lrq_r(); // (m_nsp->lrq_r() && (m_nsp->sby_r() != 0)) ? 0x00 : 0x01;
+ break;
+ default:
+ data = m_rom->base()[offset & 0x7ff];
+ break;
+ }
+
+ return data;
+}
+
+WRITE8_MEMBER(spectrum_uspeech_device::mreq_w)
+{
+ switch (offset)
+ {
+ case 0x1000:
+ // allophone
+ m_nsp->ald_w(space, 0, data & 0x3f);
+ break;
+
+ case 0x3000:
+ // intonation low
+ m_nsp->set_clock(3500000); // CK / 4 ??
+ break;
+
+ case 0x3001:
+ // intonation high
+ m_nsp->set_clock(3800000); // TODO: the exact frequency is unknown
+ break;
+ }
+}
diff --git a/src/devices/bus/spectrum/uspeech.h b/src/devices/bus/spectrum/uspeech.h
new file mode 100644
index 00000000000..b3209f80331
--- /dev/null
+++ b/src/devices/bus/spectrum/uspeech.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes,Thomas Busse
+/**********************************************************************
+
+ Spectrum Currah MicroSpeech emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_SPECTRUM_USPEECH_H
+#define MAME_BUS_SPECTRUM_USPEECH_H
+
+#pragma once
+
+
+#include "exp.h"
+#include "sound/sp0256.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> spectrum_uspeech_device
+
+class spectrum_uspeech_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_uspeech_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual DECLARE_READ8_MEMBER(mreq_r) override;
+ virtual DECLARE_WRITE8_MEMBER(mreq_w) override;
+
+private:
+ required_device<sp0256_device> m_nsp;
+ required_memory_region m_rom;
+
+ int m_romcs;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_USPEECH, spectrum_uspeech_device)
+
+
+#endif // MAME_BUS_SPECTRUM_USPEECH_H
diff --git a/src/mame/drivers/atm.cpp b/src/mame/drivers/atm.cpp
index 9d0fe3c319c..32d65b443c8 100644
--- a/src/mame/drivers/atm.cpp
+++ b/src/mame/drivers/atm.cpp
@@ -106,6 +106,13 @@ READ8_MEMBER(atm_state::beta_disable_r)
return m_program->read_byte(offset + 0x4000);
}
+static ADDRESS_MAP_START(atm_mem, AS_PROGRAM, 8, atm_state)
+ AM_RANGE(0x0000, 0x3fff) AM_ROMBANK("bank1")
+ AM_RANGE(0x4000, 0x7fff) AM_RAMBANK("bank2")
+ AM_RANGE(0x8000, 0xbfff) AM_RAMBANK("bank3")
+ AM_RANGE(0xc000, 0xffff) AM_RAMBANK("bank4")
+ADDRESS_MAP_END
+
static ADDRESS_MAP_START (atm_io, AS_IO, 8, atm_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x001f, 0x001f) AM_DEVREADWRITE(BETA_DISK_TAG, beta_disk_device, status_r, command_w) AM_MIRROR(0xff00)
@@ -173,6 +180,7 @@ GFXDECODE_END
static MACHINE_CONFIG_DERIVED( atm, spectrum_128 )
MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_PROGRAM_MAP(atm_mem)
MCFG_CPU_IO_MAP(atm_io)
MCFG_CPU_DECRYPTED_OPCODES_MAP(atm_switch)
MCFG_MACHINE_RESET_OVERRIDE(atm_state, atm )
@@ -180,6 +188,8 @@ static MACHINE_CONFIG_DERIVED( atm, spectrum_128 )
MCFG_BETA_DISK_ADD(BETA_DISK_TAG)
MCFG_GFXDECODE_MODIFY("gfxdecode", atm)
+
+ MCFG_DEVICE_REMOVE("exp")
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( atmtb2, atm )
diff --git a/src/mame/drivers/pentagon.cpp b/src/mame/drivers/pentagon.cpp
index a1c8e5763ca..cc053c8e12e 100644
--- a/src/mame/drivers/pentagon.cpp
+++ b/src/mame/drivers/pentagon.cpp
@@ -175,6 +175,13 @@ READ8_MEMBER(pentagon_state::beta_disable_r)
return m_program->read_byte(offset + 0x4000);
}
+static ADDRESS_MAP_START(pentagon_mem, AS_PROGRAM, 8, pentagon_state)
+ AM_RANGE(0x0000, 0x3fff) AM_ROMBANK("bank1")
+ AM_RANGE(0x4000, 0x7fff) AM_RAMBANK("bank2")
+ AM_RANGE(0x8000, 0xbfff) AM_RAMBANK("bank3")
+ AM_RANGE(0xc000, 0xffff) AM_RAMBANK("bank4")
+ADDRESS_MAP_END
+
static ADDRESS_MAP_START (pentagon_io, AS_IO, 8, pentagon_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x0000, 0x0000) AM_WRITE(pentagon_port_7ffd_w) AM_MIRROR(0x7ffd) // (A15 | A1) == 0
@@ -244,6 +251,7 @@ GFXDECODE_END
static MACHINE_CONFIG_DERIVED( pentagon, spectrum_128 )
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_CLOCK(XTAL_14MHz / 4)
+ MCFG_CPU_PROGRAM_MAP(pentagon_mem)
MCFG_CPU_IO_MAP(pentagon_io)
MCFG_CPU_DECRYPTED_OPCODES_MAP(pentagon_switch)
MCFG_CPU_VBLANK_INT_DRIVER("screen", pentagon_state, pentagon_interrupt)
@@ -264,6 +272,8 @@ static MACHINE_CONFIG_DERIVED( pentagon, spectrum_128 )
MCFG_SOUND_ROUTE(1, "rspeaker", 0.25)
MCFG_SOUND_ROUTE(2, "rspeaker", 0.50)
+ MCFG_DEVICE_REMOVE("exp")
+
MCFG_SOFTWARE_LIST_ADD("cass_list_pen","pentagon_cass")
MACHINE_CONFIG_END
diff --git a/src/mame/drivers/scorpion.cpp b/src/mame/drivers/scorpion.cpp
index 083d4634469..b62061b50b4 100644
--- a/src/mame/drivers/scorpion.cpp
+++ b/src/mame/drivers/scorpion.cpp
@@ -169,6 +169,13 @@ READ8_MEMBER(scorpion_state::beta_disable_r)
return m_program->read_byte(offset + 0x4000);
}
+static ADDRESS_MAP_START( scorpion_mem, AS_PROGRAM, 8, scorpion_state )
+ AM_RANGE(0x0000, 0x3fff) AM_ROMBANK("bank1") AM_WRITE(scorpion_0000_w)
+ AM_RANGE(0x4000, 0x7fff) AM_RAMBANK("bank2")
+ AM_RANGE(0x8000, 0xbfff) AM_RAMBANK("bank3")
+ AM_RANGE(0xc000, 0xffff) AM_RAMBANK("bank4")
+ADDRESS_MAP_END
+
static ADDRESS_MAP_START (scorpion_io, AS_IO, 8, scorpion_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x001f, 0x001f) AM_DEVREADWRITE(BETA_DISK_TAG, beta_disk_device, status_r, command_w) AM_MIRROR(0xff00)
@@ -274,6 +281,7 @@ GFXDECODE_END
static MACHINE_CONFIG_DERIVED( scorpion, spectrum_128 )
MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_PROGRAM_MAP(scorpion_mem)
MCFG_CPU_IO_MAP(scorpion_io)
MCFG_CPU_DECRYPTED_OPCODES_MAP(scorpion_switch)
@@ -288,6 +296,8 @@ static MACHINE_CONFIG_DERIVED( scorpion, spectrum_128 )
MCFG_RAM_DEFAULT_SIZE("256K")
MCFG_TIMER_DRIVER_ADD_PERIODIC("nmi_timer", scorpion_state, nmi_check_callback, attotime::from_hz(50))
+
+ MCFG_DEVICE_REMOVE("exp")
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( profi, scorpion )
diff --git a/src/mame/drivers/spec128.cpp b/src/mame/drivers/spec128.cpp
index 5e5b31fbc2e..d7d60e34e7c 100644
--- a/src/mame/drivers/spec128.cpp
+++ b/src/mame/drivers/spec128.cpp
@@ -55,7 +55,7 @@ Changes:
27/2/2000 KT - Added disk image support to Spectrum +3 driver.
27/2/2000 KT - Added joystick I/O code to the Spectrum +3 I/O handler.
14/3/2000 DJR - Tape handling dipswitch.
-26/3/2000 DJR - Snapshot files are now classifed as snapshots not
+26/3/2000 DJR - Snapshot files are now classified as snapshots not
cartridges.
04/4/2000 DJR - Spectrum 128 / +2 Support.
13/4/2000 DJR - +4 Support (unofficial 48K hack).
@@ -96,7 +96,7 @@ xx/xx/2001 KS - TS-2068 sound fixed.
interrupt routine is put. Due to unideal
bankswitching in MAME this JP were to 0001 what
causes Spectrum to reset. Fixing this problem
- made much more software runing (i.e. Paperboy).
+ made much more software running (i.e. Paperboy).
Corrected frames per second value for 48k and 128k
Sinclair machines.
There are 50.08 frames per second for Spectrum
@@ -104,9 +104,9 @@ xx/xx/2001 KS - TS-2068 sound fixed.
50.021 for Spectrum 128/+2/+2A/+3 what gives
70908 cycles for each frame.
Remapped some Spectrum+ keys.
- Pressing F3 to reset was seting 0xf7 on keyboard
+ Pressing F3 to reset was setting 0xf7 on keyboard
input port. Problem occurred for snapshots of
- some programms where it was readed as pressing
+ some programs where it was read as pressing
key 4 (which is exit in Tapecopy by R. Dannhoefer
for example).
Added support to load .SP snapshots.
@@ -115,7 +115,7 @@ xx/xx/2001 KS - TS-2068 sound fixed.
is an only difference.
08/03/2002 KS - #FF port emulation added.
Arkanoid works now, but is not playable due to
- completly messed timings.
+ completely messed timings.
Initialisation values used when determining which model is being emulated:
48K Spectrum doesn't use either port.
@@ -165,6 +165,31 @@ resulting mess can be seen in the F4 viewer display.
/****************************************************************************************************/
/* Spectrum 128 specific functions */
+WRITE8_MEMBER( spectrum_state::spectrum_128_bank1_w )
+{
+ if (m_exp->romcs())
+ m_exp->mreq_w(space, offset, data);
+}
+
+READ8_MEMBER( spectrum_state::spectrum_128_bank1_r )
+{
+ uint8_t data;
+
+ if (m_exp->romcs())
+ {
+ data = m_exp->mreq_r(space, offset);
+ }
+ else
+ {
+ /* ROM switching */
+ int ROMSelection = BIT(m_port_7ffd_data, 4);
+
+ /* rom 0 is 128K rom, rom 1 is 48 BASIC */
+ data = memregion("maincpu")->base()[0x010000 + (ROMSelection << 14) + offset];
+ }
+ return data;
+}
+
WRITE8_MEMBER(spectrum_state::spectrum_128_port_7ffd_w)
{
/* D0-D2: RAM page located at 0x0c000-0x0ffff */
@@ -199,17 +224,6 @@ void spectrum_state::spectrum_128_update_memory()
m_screen_location = messram + (7<<14);
else
m_screen_location = messram + (5<<14);
-
- if (!m_cart->exists())
- {
- /* ROM switching */
- int ROMSelection = BIT(m_port_7ffd_data, 4);
-
- /* rom 0 is 128K rom, rom 1 is 48 BASIC */
- unsigned char *ChosenROM = memregion("maincpu")->base() + 0x010000 + (ROMSelection << 14);
-
- membank("bank1")->set_base(ChosenROM);
- }
}
READ8_MEMBER( spectrum_state::spectrum_128_ula_r )
@@ -221,9 +235,6 @@ READ8_MEMBER( spectrum_state::spectrum_128_ula_r )
static ADDRESS_MAP_START (spectrum_128_io, AS_IO, 8, spectrum_state )
AM_RANGE(0x0000, 0x0000) AM_READWRITE(spectrum_port_fe_r,spectrum_port_fe_w) AM_SELECT(0xfffe)
- AM_RANGE(0x001f, 0x001f) AM_READ(spectrum_port_1f_r) AM_MIRROR(0xff00)
- AM_RANGE(0x007f, 0x007f) AM_READ(spectrum_port_7f_r) AM_MIRROR(0xff00)
- AM_RANGE(0x00df, 0x00df) AM_READ(spectrum_port_df_r) AM_MIRROR(0xff00)
AM_RANGE(0x0000, 0x0000) AM_WRITE(spectrum_128_port_7ffd_w) AM_MIRROR(0x7ffd) // (A15 | A1) == 0, note: reading from this port does write to it by value from data bus
AM_RANGE(0x8000, 0x8000) AM_DEVWRITE("ay8912", ay8910_device, data_w) AM_MIRROR(0x3ffd)
AM_RANGE(0xc000, 0xc000) AM_DEVREADWRITE("ay8912", ay8910_device, data_r, address_w) AM_MIRROR(0x3ffd)
@@ -231,7 +242,7 @@ static ADDRESS_MAP_START (spectrum_128_io, AS_IO, 8, spectrum_state )
ADDRESS_MAP_END
static ADDRESS_MAP_START (spectrum_128_mem, AS_PROGRAM, 8, spectrum_state )
- AM_RANGE( 0x0000, 0x3fff) AM_ROMBANK("bank1") // don't use RAMBANK here otherwise programs can erase the ROM(!)
+ AM_RANGE( 0x0000, 0x3fff) AM_READWRITE(spectrum_128_bank1_r, spectrum_128_bank1_w)
AM_RANGE( 0x4000, 0x7fff) AM_RAMBANK("bank2")
AM_RANGE( 0x8000, 0xbfff) AM_RAMBANK("bank3")
AM_RANGE( 0xc000, 0xffff) AM_RAMBANK("bank4")
@@ -284,7 +295,7 @@ MACHINE_CONFIG_DERIVED( spectrum_128, spectrum )
MCFG_CPU_ADD("maincpu", Z80, X1_128_SINCLAIR / 5)
MCFG_CPU_PROGRAM_MAP(spectrum_128_mem)
MCFG_CPU_IO_MAP(spectrum_128_io)
- MCFG_CPU_VBLANK_INT_DRIVER("screen", spectrum_state, spec_interrupt)
+ MCFG_CPU_VBLANK_INT_DRIVER("screen", spectrum_state, spec_interrupt)
MCFG_QUANTUM_TIME(attotime::from_hz(60))
MCFG_MACHINE_RESET_OVERRIDE(spectrum_state, spectrum_128 )
@@ -297,9 +308,13 @@ MACHINE_CONFIG_DERIVED( spectrum_128, spectrum )
MCFG_GFXDECODE_MODIFY("gfxdecode", spec128)
/* sound hardware */
- MCFG_SOUND_ADD("ay8912", AY8912, 1773400)
+ MCFG_SOUND_ADD("ay8912", AY8912, X1_128_SINCLAIR / 10)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+ /* expansion port */
+ MCFG_DEVICE_MODIFY("exp")
+ MCFG_DEVICE_SLOT_INTERFACE(spec128_expansion_devices, nullptr, false)
+
/* internal ram */
MCFG_RAM_MODIFY(RAM_TAG)
MCFG_RAM_DEFAULT_SIZE("128K")
@@ -360,7 +375,7 @@ ROM_START(hc2000)
ROM_END
// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS
-COMP( 1986, spec128, 0, 0, spectrum_128, spec_plus, spectrum_state, 0, "Sinclair Research Ltd", "ZX Spectrum 128", 0 )
+COMP( 1986, spec128, 0, 0, spectrum_128, spec128, spectrum_state, 0, "Sinclair Research Ltd", "ZX Spectrum 128", 0 )
COMP( 1986, specpls2, spec128, 0, spectrum_128, spec_plus, spectrum_state, 0, "Amstrad plc", "ZX Spectrum +2", 0 )
COMP( 1991, hc128, spec128, 0, spectrum_128, spec_plus, spectrum_state, 0, "ICE-Felix", "HC-128", 0 )
COMP( 1992, hc2000, spec128, 0, spectrum_128, spec_plus, spectrum_state, 0, "ICE-Felix", "HC-2000", MACHINE_NOT_WORKING )
diff --git a/src/mame/drivers/specpls3.cpp b/src/mame/drivers/specpls3.cpp
index a187d43958d..8b91527e701 100644
--- a/src/mame/drivers/specpls3.cpp
+++ b/src/mame/drivers/specpls3.cpp
@@ -55,7 +55,7 @@ Changes:
27/2/2000 KT - Added disk image support to Spectrum +3 driver.
27/2/2000 KT - Added joystick I/O code to the Spectrum +3 I/O handler.
14/3/2000 DJR - Tape handling dipswitch.
-26/3/2000 DJR - Snapshot files are now classifed as snapshots not
+26/3/2000 DJR - Snapshot files are now classified as snapshots not
cartridges.
04/4/2000 DJR - Spectrum 128 / +2 Support.
13/4/2000 DJR - +4 Support (unofficial 48K hack).
@@ -96,17 +96,17 @@ xx/xx/2001 KS - TS-2068 sound fixed.
interrupt routine is put. Due to unideal
bankswitching in MAME this JP were to 0001 what
causes Spectrum to reset. Fixing this problem
- made much more software runing (i.e. Paperboy).
+ made much more software running (i.e. Paperboy).
Corrected frames per second value for 48k and 128k
Sinclair machines.
There are 50.08 frames per second for Spectrum
48k what gives 69888 cycles for each frame and
50.021 for Spectrum 128/+2/+2A/+3 what gives
70908 cycles for each frame.
- Remaped some Spectrum+ keys.
- Presing F3 to reset was seting 0xf7 on keyboard
+ Remapped some Spectrum+ keys.
+ Pressing F3 to reset was setting 0xf7 on keyboard
input port. Problem occurred for snapshots of
- some programms where it was readed as pressing
+ some programs where it was read as pressing
key 4 (which is exit in Tapecopy by R. Dannhoefer
for example).
Added support to load .SP snapshots.
@@ -115,7 +115,7 @@ xx/xx/2001 KS - TS-2068 sound fixed.
is an only difference.
08/03/2002 KS - #FF port emulation added.
Arkanoid works now, but is not playable due to
- completly messed timings.
+ completely messed timings.
Initialisation values used when determining which model is being emulated:
48K Spectrum doesn't use either port.
@@ -228,19 +228,16 @@ void spectrum_state::spectrum_plus3_update_memory()
/* Bank 2 in 0x8000 - 0xbfff */
membank("bank3")->set_base(messram + (2 << 14));
- if (!m_cart->exists())
- {
- /* ROM switching */
- int ROMSelection = BIT(m_port_7ffd_data, 4) | ((m_port_1ffd_data >> 1) & 0x02);
+ /* ROM switching */
+ int ROMSelection = BIT(m_port_7ffd_data, 4) | ((m_port_1ffd_data >> 1) & 0x02);
- /* rom 0 is editor, rom 1 is syntax, rom 2 is DOS, rom 3 is 48 BASIC */
- unsigned char *ChosenROM = memregion("maincpu")->base() + 0x010000 + (ROMSelection << 14);
+ /* rom 0 is editor, rom 1 is syntax, rom 2 is DOS, rom 3 is 48 BASIC */
+ unsigned char *ChosenROM = memregion("maincpu")->base() + 0x010000 + (ROMSelection << 14);
- membank("bank1")->set_base(ChosenROM);
- space.unmap_write(0x0000, 0x3fff);
+ membank("bank1")->set_base(ChosenROM);
+ space.unmap_write(0x0000, 0x3fff);
- logerror("rom switch: %02x\n", ROMSelection);
- }
+ logerror("rom switch: %02x\n", ROMSelection);
}
else
{
@@ -311,7 +308,6 @@ The function decodes the ports appropriately */
static ADDRESS_MAP_START (spectrum_plus3_io, AS_IO, 8, spectrum_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x0000, 0x0000) AM_READWRITE(spectrum_port_fe_r,spectrum_port_fe_w) AM_SELECT(0xfffe)
- AM_RANGE(0x001f, 0x001f) AM_READ(spectrum_port_1f_r) AM_MIRROR(0xff00)
AM_RANGE(0x4000, 0x4000) AM_WRITE(spectrum_plus3_port_7ffd_w) AM_MIRROR(0x3ffd)
AM_RANGE(0x8000, 0x8000) AM_DEVWRITE("ay8912", ay8910_device, data_w) AM_MIRROR(0x3ffd)
AM_RANGE(0xc000, 0xc000) AM_DEVREADWRITE("ay8912", ay8910_device, data_r, address_w) AM_MIRROR(0x3ffd)
@@ -320,6 +316,13 @@ static ADDRESS_MAP_START (spectrum_plus3_io, AS_IO, 8, spectrum_state )
AM_RANGE(0x3000, 0x3000) AM_READWRITE(spectrum_plus3_port_3ffd_r,spectrum_plus3_port_3ffd_w) AM_MIRROR(0x0ffd)
ADDRESS_MAP_END
+static ADDRESS_MAP_START(spectrum_plus3_mem, AS_PROGRAM, 8, spectrum_state)
+ AM_RANGE(0x0000, 0x3fff) AM_ROMBANK("bank1")
+ AM_RANGE(0x4000, 0x7fff) AM_RAMBANK("bank2")
+ AM_RANGE(0x8000, 0xbfff) AM_RAMBANK("bank3")
+ AM_RANGE(0xc000, 0xffff) AM_RAMBANK("bank4")
+ADDRESS_MAP_END
+
MACHINE_RESET_MEMBER(spectrum_state,spectrum_plus3)
{
uint8_t *messram = m_ram->pointer();
@@ -368,6 +371,7 @@ GFXDECODE_END
static MACHINE_CONFIG_DERIVED( spectrum_plus3, spectrum_128 )
MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_PROGRAM_MAP(spectrum_plus3_mem)
MCFG_CPU_IO_MAP(spectrum_plus3_io)
MCFG_SCREEN_MODIFY("screen")
MCFG_SCREEN_REFRESH_RATE(50.01)
@@ -379,6 +383,9 @@ static MACHINE_CONFIG_DERIVED( spectrum_plus3, spectrum_128 )
MCFG_FLOPPY_DRIVE_ADD("upd765:0", specpls3_floppies, "3ssdd", floppy_image_device::default_floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("upd765:1", specpls3_floppies, "3ssdd", floppy_image_device::default_floppy_formats)
+ MCFG_DEVICE_MODIFY("exp")
+ MCFG_DEVICE_SLOT_INTERFACE(specpls3_expansion_devices, nullptr, false)
+
MCFG_SOFTWARE_LIST_ADD("flop_list", "specpls3_flop")
MACHINE_CONFIG_END
@@ -452,10 +459,10 @@ ROM_START(sp3eata)
ROMX_LOAD("3ezxaes.rom",0x10000,0x10000, CRC(8f0ae91a) SHA1(71693e18b30c90914be58cba26682ca025c924ea), ROM_BIOS(2))
ROM_END
-/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */
-COMP( 1987, specpl2a, spec128, 0, spectrum_plus3, spec_plus, spectrum_state, plus2, "Amstrad plc", "ZX Spectrum +2a" , 0 )
-COMP( 1987, specpls3, spec128, 0, spectrum_plus3, spec_plus, spectrum_state, plus3, "Amstrad plc", "ZX Spectrum +3" , 0 )
-COMP( 2000, specpl3e, spec128, 0, spectrum_plus3, spec_plus, spectrum_state, plus3, "Amstrad plc", "ZX Spectrum +3e" , MACHINE_UNOFFICIAL )
-COMP( 2002, sp3e8bit, spec128, 0, spectrum_plus3, spec_plus, spectrum_state, plus3, "Amstrad plc", "ZX Spectrum +3e 8bit IDE" , MACHINE_UNOFFICIAL )
+/* YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS */
+COMP( 1987, specpl2a, spec128, 0, spectrum_plus3, spec_plus, spectrum_state, plus2, "Amstrad plc", "ZX Spectrum +2a", 0 )
+COMP( 1987, specpls3, spec128, 0, spectrum_plus3, spec_plus, spectrum_state, plus3, "Amstrad plc", "ZX Spectrum +3", 0 )
+COMP( 2000, specpl3e, spec128, 0, spectrum_plus3, spec_plus, spectrum_state, plus3, "Amstrad plc", "ZX Spectrum +3e", MACHINE_UNOFFICIAL )
+COMP( 2002, sp3e8bit, spec128, 0, spectrum_plus3, spec_plus, spectrum_state, plus3, "Amstrad plc", "ZX Spectrum +3e 8bit IDE", MACHINE_UNOFFICIAL )
COMP( 2002, sp3eata, spec128, 0, spectrum_plus3, spec_plus, spectrum_state, plus3, "Amstrad plc", "ZX Spectrum +3e 8bit ZXATASP" , MACHINE_UNOFFICIAL )
-COMP( 2002, sp3ezcf, spec128, 0, spectrum_plus3, spec_plus, spectrum_state, plus3, "Amstrad plc", "ZX Spectrum +3e 8bit ZXCF" , MACHINE_UNOFFICIAL )
+COMP( 2002, sp3ezcf, spec128, 0, spectrum_plus3, spec_plus, spectrum_state, plus3, "Amstrad plc", "ZX Spectrum +3e 8bit ZXCF", MACHINE_UNOFFICIAL )
diff --git a/src/mame/drivers/spectrum.cpp b/src/mame/drivers/spectrum.cpp
index dce710d7140..a4c465b56d6 100644
--- a/src/mame/drivers/spectrum.cpp
+++ b/src/mame/drivers/spectrum.cpp
@@ -55,7 +55,7 @@ Changes:
27/2/2000 KT - Added disk image support to Spectrum +3 driver.
27/2/2000 KT - Added joystick I/O code to the Spectrum +3 I/O handler.
14/3/2000 DJR - Tape handling dipswitch.
-26/3/2000 DJR - Snapshot files are now classifed as snapshots not
+26/3/2000 DJR - Snapshot files are now classified as snapshots not
cartridges.
04/4/2000 DJR - Spectrum 128 / +2 Support.
13/4/2000 DJR - +4 Support (unofficial 48K hack).
@@ -96,17 +96,17 @@ xx/xx/2001 KS - TS-2068 sound fixed.
interrupt routine is put. Due to unideal
bankswitching in MAME this JP were to 0001 what
causes Spectrum to reset. Fixing this problem
- made much more software runing (i.e. Paperboy).
+ made much more software running (i.e. Paperboy).
Corrected frames per second value for 48k and 128k
- Sincalir machines.
+ Sinclair machines.
There are 50.08 frames per second for Spectrum
48k what gives 69888 cycles for each frame and
50.021 for Spectrum 128/+2/+2A/+3 what gives
70908 cycles for each frame.
- Remaped some Spectrum+ keys.
- Presing F3 to reset was seting 0xf7 on keyboard
+ Remapped some Spectrum+ keys.
+ Pressing F3 to reset was setting 0xf7 on keyboard
input port. Problem occurred for snapshots of
- some programms where it was readed as pressing
+ some programs where it was read as pressing
key 4 (which is exit in Tapecopy by R. Dannhoefer
for example).
Added support to load .SP snapshots.
@@ -115,7 +115,7 @@ xx/xx/2001 KS - TS-2068 sound fixed.
is an only difference.
08/03/2002 KS - #FF port emulation added.
Arkanoid works now, but is not playable due to
- completly messed timings.
+ completely messed timings.
25/10/2012 DH - simplified border emulation to be a (manual) partial
update with bitmap
Removed legacy fff4 interrupt hack, modern version of
@@ -292,6 +292,24 @@ SamRam
/****************************************************************************************************/
/* Spectrum 48k functions */
+WRITE8_MEMBER(spectrum_state::spectrum_rom_w)
+{
+ if (m_exp->romcs())
+ m_exp->mreq_w(space, offset, data);
+}
+
+READ8_MEMBER(spectrum_state::spectrum_rom_r)
+{
+ uint8_t data;
+
+ data = m_exp->mreq_r(space, offset);
+
+ if (!m_exp->romcs())
+ data = memregion("maincpu")->base()[offset];
+
+ return data;
+}
+
/*
bit 7-5: not used
bit 4: Ear output/Speaker
@@ -327,7 +345,6 @@ WRITE8_MEMBER(spectrum_state::spectrum_port_fe_w)
}
-
/* KT: more accurate keyboard reading */
/* DJR: Spectrum+ keys added */
READ8_MEMBER(spectrum_state::spectrum_port_fe_r)
@@ -340,6 +357,8 @@ READ8_MEMBER(spectrum_state::spectrum_port_fe_r)
int cs_extra3 = m_io_plus2.read_safe(0x1f) & 0x1f;
int ss_extra1 = m_io_plus3.read_safe(0x1f) & 0x1f;
int ss_extra2 = m_io_plus4.read_safe(0x1f) & 0x1f;
+ int joy1 = m_io_joy1.read_safe(0x1f) & 0x1f;
+ int joy2 = m_io_joy2.read_safe(0x1f) & 0x1f;
/* Caps - V */
if ((lines & 1) == 0)
@@ -360,11 +379,11 @@ READ8_MEMBER(spectrum_state::spectrum_port_fe_r)
/* 1 - 5 */
if ((lines & 8) == 0)
- data &= m_io_line3->read() & cs_extra1;
+ data &= m_io_line3->read() & cs_extra1 & joy2;
/* 6 - 0 */
if ((lines & 16) == 0)
- data &= m_io_line4->read() & cs_extra2;
+ data &= m_io_line4->read() & cs_extra2 & joy1;
/* Y - P */
if ((lines & 32) == 0)
@@ -374,7 +393,7 @@ READ8_MEMBER(spectrum_state::spectrum_port_fe_r)
if ((lines & 64) == 0)
data &= m_io_line6->read();
- /* B - Space */
+ /* B - Space */
if ((lines & 128) == 0)
{
data &= m_io_line7->read() & cs_extra3 & ss_extra2;
@@ -391,6 +410,10 @@ READ8_MEMBER(spectrum_state::spectrum_port_fe_r)
data &= ~0x40;
}
+ /* expansion port */
+ if (m_exp)
+ data &= m_exp->port_fe_r(space, offset);
+
/* Issue 2 Spectrums default to having bits 5, 6 & 7 set.
Issue 3 Spectrums default to having bits 5 & 7 set and bit 6 reset. */
if (m_io_config->read() & 0x80)
@@ -399,24 +422,6 @@ READ8_MEMBER(spectrum_state::spectrum_port_fe_r)
return data;
}
-/* kempston joystick interface */
-READ8_MEMBER(spectrum_state::spectrum_port_1f_r)
-{
- return m_io_kempston->read() & 0x1f;
-}
-
-/* fuller joystick interface */
-READ8_MEMBER(spectrum_state::spectrum_port_7f_r)
-{
- return m_io_fuller->read() | (0xff^0x8f);
-}
-
-/* mikrogen joystick interface */
-READ8_MEMBER(spectrum_state::spectrum_port_df_r)
-{
- return m_io_mikrogen->read() | (0xff^0x1f);
-}
-
READ8_MEMBER(spectrum_state::spectrum_port_ula_r)
{
int vpos = machine().first_screen()->vpos();
@@ -427,7 +432,7 @@ READ8_MEMBER(spectrum_state::spectrum_port_ula_r)
/* Memory Maps */
static ADDRESS_MAP_START (spectrum_mem, AS_PROGRAM, 8, spectrum_state )
- AM_RANGE(0x0000, 0x3fff) AM_ROM
+ AM_RANGE(0x0000, 0x3fff) AM_READWRITE(spectrum_rom_r, spectrum_rom_w)
AM_RANGE(0x4000, 0x5aff) AM_RAM AM_SHARE("video_ram")
// AM_RANGE(0x5b00, 0x7fff) AM_RAM
// AM_RANGE(0x8000, 0xffff) AM_RAM
@@ -436,10 +441,7 @@ ADDRESS_MAP_END
/* ports are not decoded full.
The function decodes the ports appropriately */
static ADDRESS_MAP_START (spectrum_io, AS_IO, 8, spectrum_state )
- AM_RANGE(0x00, 0x00) AM_READWRITE(spectrum_port_fe_r,spectrum_port_fe_w) AM_SELECT(0xfffe)
- AM_RANGE(0x1f, 0x1f) AM_READ(spectrum_port_1f_r) AM_MIRROR(0xff00)
- AM_RANGE(0x7f, 0x7f) AM_READ(spectrum_port_7f_r) AM_MIRROR(0xff00)
- AM_RANGE(0xdf, 0xdf) AM_READ(spectrum_port_df_r) AM_MIRROR(0xff00)
+ AM_RANGE(0x00, 0x00) AM_READWRITE(spectrum_port_fe_r, spectrum_port_fe_w) AM_SELECT(0xfffe)
AM_RANGE(0x01, 0x01) AM_READ(spectrum_port_ula_r) AM_MIRROR(0xfffe)
ADDRESS_MAP_END
@@ -447,34 +449,20 @@ ADDRESS_MAP_END
/****************************************************************************************************/
-static INPUT_PORTS_START( spec_joys )
- PORT_START("JOY_INTF")
- PORT_CONFNAME( 0x0f, 0x01, "Joystick Interface")
- PORT_CONFSETTING( 0x00, "None (No Joystick)" )
- PORT_CONFSETTING( 0x01, "Kempston" )
- PORT_CONFSETTING( 0x02, "Fuller" )
- PORT_CONFSETTING( 0x03, "Mikrogen" )
-
- PORT_START("KEMPSTON") /* Kempston joystick interface */
- PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("P1 Joystick Right (Kempston)") PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x01)
- PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("P1 Joystick Left (Kempston)") PORT_CODE(JOYCODE_X_LEFT_SWITCH) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x01)
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("P1 Joystick Down (Kempston)") PORT_CODE(JOYCODE_Y_DOWN_SWITCH) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x01)
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("P1 Joystick Up (Kempston)") PORT_CODE(JOYCODE_Y_UP_SWITCH) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x01)
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("P1 Joystick Fire (Kempston)") PORT_CODE(JOYCODE_BUTTON1) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x01)
-
- PORT_START("FULLER") /* Fuller joystick interface */
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P1 Joystick Up (Fuller)") PORT_CODE(JOYCODE_Y_UP_SWITCH) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x02)
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P1 Joystick Down (Fuller)") PORT_CODE(JOYCODE_Y_DOWN_SWITCH) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x02)
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P1 Joystick Left (Fuller)") PORT_CODE(JOYCODE_X_LEFT_SWITCH) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x02)
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P1 Joystick Right (Fuller)") PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x02)
- PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P1 Joystick Fire (Fuller)") PORT_CODE(JOYCODE_BUTTON1) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x02)
-
- PORT_START("MIKROGEN") /* Mikrogen joystick interface */
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P1 Joystick Up (Mikrogen)") PORT_CODE(JOYCODE_Y_UP_SWITCH) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x03)
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P1 Joystick Down (Mikrogen)") PORT_CODE(JOYCODE_Y_DOWN_SWITCH) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x03)
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P1 Joystick Right (Mikrogen)") PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x03)
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P1 Joystick Left (Mikrogen)") PORT_CODE(JOYCODE_X_LEFT_SWITCH) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x03)
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P1 Joystick Fire (Mikrogen)") PORT_CODE(JOYCODE_BUTTON1) PORT_CONDITION("JOY_INTF", 0x0f, EQUALS, 0x03)
+static INPUT_PORTS_START( spec_plus_joys )
+ PORT_START("JOY2") /* 0xF7FE */
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_X_LEFT_SWITCH)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_X_RIGHT_SWITCH)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_Y_UP_SWITCH)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2) PORT_CODE(JOYCODE_BUTTON1)
+
+ PORT_START("JOY1") /* 0xEFFE */
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1) PORT_CODE(JOYCODE_BUTTON1)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(1) PORT_CODE(JOYCODE_Y_UP_SWITCH)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(1) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(1) PORT_CODE(JOYCODE_X_RIGHT_SWITCH)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(1) PORT_CODE(JOYCODE_X_LEFT_SWITCH)
INPUT_PORTS_END
/*
@@ -570,13 +558,11 @@ INPUT_PORTS_START( spectrum )
PORT_CONFSETTING( 0x00, "Issue 2" )
PORT_CONFSETTING( 0x80, "Issue 3" )
PORT_BIT(0x7f, IP_ACTIVE_LOW, IPT_UNUSED)
-
- PORT_INCLUDE( spec_joys )
INPUT_PORTS_END
/* These keys need not to be mapped in natural mode because Spectrum+ supports both these and the Spectrum sequences above.
Hence, we can simply keep using such sequences in natural keyboard emulation */
-INPUT_PORTS_START( spec_plus )
+INPUT_PORTS_START( spec128 )
PORT_INCLUDE( spectrum )
PORT_START("PLUS0") /* Spectrum+ Keys (Same as CAPS + 1-5) */
@@ -611,6 +597,11 @@ INPUT_PORTS_START( spec_plus )
PORT_BIT(0xf3, IP_ACTIVE_LOW, IPT_UNUSED)
INPUT_PORTS_END
+INPUT_PORTS_START( spec_plus )
+ PORT_INCLUDE( spec128 )
+ PORT_INCLUDE( spec_plus_joys )
+INPUT_PORTS_END
+
/* Machine initialization */
DRIVER_INIT_MEMBER(spectrum_state,spectrum)
@@ -630,9 +621,6 @@ MACHINE_RESET_MEMBER(spectrum_state,spectrum)
{
m_port_7ffd_data = -1;
m_port_1ffd_data = -1;
-
- if (m_cart && m_cart->exists())
- m_maincpu->space(AS_PROGRAM).install_read_handler(0x0000, 0x3fff, read8_delegate(FUNC(generic_slot_device::read_rom),(generic_slot_device*)m_cart));
}
/* F4 Character Displayer */
@@ -664,29 +652,13 @@ INTERRUPT_GEN_MEMBER(spectrum_state::spec_interrupt)
timer_set(attotime::from_ticks(32, m_maincpu->clock()), 0, 0);
}
-DEVICE_IMAGE_LOAD_MEMBER(spectrum_state, spectrum_cart)
-{
- uint32_t size = m_cart->common_get_size("rom");
-
- if (size != 0x4000)
- {
- image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size");
- return image_init_result::FAIL;
- }
-
- m_cart->rom_alloc(size, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
- m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom");
-
- return image_init_result::PASS;
-}
-
MACHINE_CONFIG_START( spectrum_common )
/* basic machine hardware */
- MCFG_CPU_ADD("maincpu", Z80, X1 / 4) /* This is verified only for the ZX Spectum. Other clones are reported to have different clocks */
+ MCFG_CPU_ADD("maincpu", Z80, X1 / 4) /* This is verified only for the ZX Spectrum. Other clones are reported to have different clocks */
MCFG_CPU_PROGRAM_MAP(spectrum_mem)
MCFG_CPU_IO_MAP(spectrum_io)
- MCFG_CPU_VBLANK_INT_DRIVER("screen", spectrum_state, spec_interrupt)
+ MCFG_CPU_VBLANK_INT_DRIVER("screen", spectrum_state, spec_interrupt)
MCFG_QUANTUM_TIME(attotime::from_hz(60))
MCFG_MACHINE_RESET_OVERRIDE(spectrum_state, spectrum )
@@ -713,6 +685,9 @@ MACHINE_CONFIG_START( spectrum_common )
MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+ /* expansion port */
+ MCFG_SPECTRUM_EXPANSION_SLOT_ADD("exp", spectrum_expansion_devices, "kempjoy")
+
/* devices */
MCFG_SNAPSHOT_ADD("snapshot", spectrum_state, spectrum, "ach,frz,plusd,prg,sem,sit,sna,snp,snx,sp,z80,zx", 0)
MCFG_QUICKLOAD_ADD("quickload", spectrum_state, spectrum, "raw,scr", 2) // The delay prevents the screen from being cleared by the RAM test at boot
@@ -722,13 +697,6 @@ MACHINE_CONFIG_START( spectrum_common )
MCFG_CASSETTE_INTERFACE("spectrum_cass")
MCFG_SOFTWARE_LIST_ADD("cass_list", "spectrum_cass")
-
- /* cartridge */
- MCFG_GENERIC_CARTSLOT_ADD("cartslot", generic_plain_slot, "spectrum_cart")
- MCFG_GENERIC_EXTENSIONS("bin,rom")
- MCFG_GENERIC_LOAD(spectrum_state, spectrum_cart)
-
- MCFG_SOFTWARE_LIST_ADD("cart_list", "spectrum_cart")
MACHINE_CONFIG_END
MACHINE_CONFIG_DERIVED( spectrum, spectrum_common )
diff --git a/src/mame/drivers/timex.cpp b/src/mame/drivers/timex.cpp
index c839f8bfaa8..c6ddea29a22 100644
--- a/src/mame/drivers/timex.cpp
+++ b/src/mame/drivers/timex.cpp
@@ -55,7 +55,7 @@ Changes:
27/2/2000 KT - Added disk image support to Spectrum +3 driver.
27/2/2000 KT - Added joystick I/O code to the Spectrum +3 I/O handler.
14/3/2000 DJR - Tape handling dipswitch.
-26/3/2000 DJR - Snapshot files are now classifed as snapshots not
+26/3/2000 DJR - Snapshot files are now classified as snapshots not
cartridges.
04/4/2000 DJR - Spectrum 128 / +2 Support.
13/4/2000 DJR - +4 Support (unofficial 48K hack).
@@ -96,17 +96,17 @@ xx/xx/2001 KS - TS-2068 sound fixed.
interrupt routine is put. Due to unideal
bankswitching in MAME this JP were to 0001 what
causes Spectrum to reset. Fixing this problem
- made much more software runing (i.e. Paperboy).
+ made much more software running (i.e. Paperboy).
Corrected frames per second value for 48k and 128k
- Sincalir machines.
+ Sinclair machines.
There are 50.08 frames per second for Spectrum
48k what gives 69888 cycles for each frame and
50.021 for Spectrum 128/+2/+2A/+3 what gives
70908 cycles for each frame.
- Remaped some Spectrum+ keys.
- Presing F3 to reset was seting 0xf7 on keyboard
+ Remapped some Spectrum+ keys.
+ Pressing F3 to reset was setting 0xf7 on keyboard
input port. Problem occurred for snapshots of
- some programms where it was readed as pressing
+ some programs where it was read as pressing
key 4 (which is exit in Tapecopy by R. Dannhoefer
for example).
Added support to load .SP snapshots.
@@ -115,7 +115,7 @@ xx/xx/2001 KS - TS-2068 sound fixed.
is an only difference.
08/03/2002 KS - #FF port emulation added.
Arkanoid works now, but is not playable due to
- completly messed timings.
+ completely messed timings.
Initialisation values used when determining which model is being emulated:
48K Spectrum doesn't use either port.
@@ -208,7 +208,7 @@ WRITE8_MEMBER( spectrum_state::ts2068_port_ff_w )
* etc. If the bit is 0 then the chunk is controlled by the HOME
* bank. If the bit is 1 then the chunk is controlled by either
* the DOCK or EXROM depending on bit 7 of port #ff. Note this
- * means that that the Z80 can't see chunks of the EXROM and DOCK
+ * means that the Z80 can't see chunks of the EXROM and DOCK
* at the same time.
*
*******************************************************************/
@@ -526,9 +526,6 @@ void spectrum_state::ts2068_update_memory()
}
static ADDRESS_MAP_START(ts2068_io, AS_IO, 8, spectrum_state )
- AM_RANGE(0x1f, 0x1f) AM_READ(spectrum_port_1f_r ) AM_MIRROR(0xff00)
- AM_RANGE(0x7f, 0x7f) AM_READ(spectrum_port_7f_r ) AM_MIRROR(0xff00)
- AM_RANGE(0xdf, 0xdf) AM_READ(spectrum_port_df_r ) AM_MIRROR(0xff00)
AM_RANGE(0xf4, 0xf4) AM_READWRITE(ts2068_port_f4_r,ts2068_port_f4_w ) AM_MIRROR(0xff00)
AM_RANGE(0xf5, 0xf5) AM_DEVWRITE("ay8912", ay8910_device, address_w ) AM_MIRROR(0xff00)
AM_RANGE(0xf6, 0xf6) AM_DEVREADWRITE("ay8912", ay8910_device, data_r, data_w ) AM_MIRROR(0xff00)
@@ -574,9 +571,6 @@ WRITE8_MEMBER( spectrum_state::tc2048_port_ff_w )
static ADDRESS_MAP_START(tc2048_io, AS_IO, 8, spectrum_state )
AM_RANGE(0x00, 0x00) AM_READWRITE(spectrum_port_fe_r,spectrum_port_fe_w) AM_SELECT(0xfffe)
- AM_RANGE(0x1f, 0x1f) AM_READ(spectrum_port_1f_r) AM_MIRROR(0xff00)
- AM_RANGE(0x7f, 0x7f) AM_READ(spectrum_port_7f_r) AM_MIRROR(0xff00)
- AM_RANGE(0xdf, 0xdf) AM_READ(spectrum_port_df_r) AM_MIRROR(0xff00)
AM_RANGE(0xff, 0xff) AM_READWRITE(ts2068_port_ff_r,tc2048_port_ff_w) AM_MIRROR(0xff00)
ADDRESS_MAP_END
@@ -714,13 +708,11 @@ static MACHINE_CONFIG_DERIVED( ts2068, spectrum_128 )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
/* cartridge */
- MCFG_DEVICE_REMOVE("cartslot")
MCFG_GENERIC_CARTSLOT_ADD("dockslot", generic_plain_slot, "timex_cart")
MCFG_GENERIC_EXTENSIONS("dck,bin")
MCFG_GENERIC_LOAD(spectrum_state, timex_cart)
/* Software lists */
- MCFG_DEVICE_REMOVE("cart_list")
MCFG_SOFTWARE_LIST_ADD("cart_list", "timex_dock")
/* internal ram */
diff --git a/src/mame/includes/spectrum.h b/src/mame/includes/spectrum.h
index e787e23baab..28b6c128129 100644
--- a/src/mame/includes/spectrum.h
+++ b/src/mame/includes/spectrum.h
@@ -13,6 +13,7 @@
#include "machine/spec_snqk.h"
+#include "bus/spectrum/exp.h"
#include "bus/generic/carts.h"
#include "bus/generic/slot.h"
#include "imagedev/cassette.h"
@@ -45,7 +46,7 @@
#define SPEC_LEFT_BORDER_CYCLES 24 /* Cycles to display left hand border */
#define SPEC_DISPLAY_XSIZE_CYCLES 128 /* Horizontal screen resolution */
#define SPEC_RIGHT_BORDER_CYCLES 24 /* Cycles to display right hand border */
-#define SPEC_RETRACE_CYCLES 48 /* Cycles taken for horizonal retrace */
+#define SPEC_RETRACE_CYCLES 48 /* Cycles taken for horizontal retrace */
#define SPEC_CYCLES_PER_LINE 224 /* Number of cycles to display a single line */
struct EVENT_LIST_ITEM
@@ -69,7 +70,7 @@ public:
m_cassette(*this, "cassette"),
m_ram(*this, RAM_TAG),
m_speaker(*this, "speaker"),
- m_cart(*this, "cartslot"),
+ m_exp(*this, "exp"),
m_dock(*this, "dockslot"),
m_upd765(*this, "upd765"),
m_upd765_0(*this, "upd765:0"),
@@ -84,15 +85,13 @@ public:
m_io_line7(*this, "LINE7"),
m_io_nmi(*this, "NMI"),
m_io_config(*this, "CONFIG"),
- m_io_joy_intf(*this, "JOY_INTF"),
- m_io_kempston(*this, "KEMPSTON"),
- m_io_fuller(*this, "FULLER"),
- m_io_mikrogen(*this, "MIKROGEN"),
m_io_plus0(*this, "PLUS0"),
m_io_plus1(*this, "PLUS1"),
m_io_plus2(*this, "PLUS2"),
m_io_plus3(*this, "PLUS3"),
- m_io_plus4(*this, "PLUS4") { }
+ m_io_plus4(*this, "PLUS4"),
+ m_io_joy1(*this, "JOY1"),
+ m_io_joy2(*this, "JOY2") { }
int m_port_fe_data;
int m_port_7ffd_data;
@@ -121,16 +120,19 @@ public:
uint8_t *m_ram_0000;
uint8_t m_ram_disabled_by_beta;
+ DECLARE_WRITE8_MEMBER(spectrum_rom_w);
+ DECLARE_READ8_MEMBER(spectrum_rom_r);
DECLARE_WRITE8_MEMBER(spectrum_port_fe_w);
DECLARE_READ8_MEMBER(spectrum_port_fe_r);
- DECLARE_READ8_MEMBER(spectrum_port_1f_r);
- DECLARE_READ8_MEMBER(spectrum_port_7f_r);
- DECLARE_READ8_MEMBER(spectrum_port_df_r);
DECLARE_READ8_MEMBER(spectrum_port_ula_r);
+ DECLARE_WRITE8_MEMBER(spectrum_128_bank1_w);
+ DECLARE_READ8_MEMBER(spectrum_128_bank1_r);
DECLARE_WRITE8_MEMBER(spectrum_128_port_7ffd_w);
DECLARE_READ8_MEMBER(spectrum_128_ula_r);
+ DECLARE_WRITE8_MEMBER(spectrum_plus3_bank1_w);
+ DECLARE_READ8_MEMBER(spectrum_plus3_bank1_r);
DECLARE_WRITE8_MEMBER(spectrum_plus3_port_3ffd_w);
DECLARE_READ8_MEMBER(spectrum_plus3_port_3ffd_r);
DECLARE_READ8_MEMBER(spectrum_plus3_port_2ffd_r);
@@ -161,7 +163,6 @@ public:
DECLARE_WRITE_LINE_MEMBER(screen_vblank_spectrum);
DECLARE_WRITE_LINE_MEMBER(screen_vblank_timex);
INTERRUPT_GEN_MEMBER(spec_interrupt);
- DECLARE_DEVICE_IMAGE_LOAD_MEMBER( spectrum_cart );
// for timex cart only
DECLARE_DEVICE_IMAGE_LOAD_MEMBER( timex_cart );
@@ -187,7 +188,7 @@ protected:
required_device<cassette_image_device> m_cassette;
required_device<ram_device> m_ram;
required_device<speaker_sound_device> m_speaker;
- optional_device<generic_slot_device> m_cart;
+ optional_device<spectrum_expansion_slot_device> m_exp;
optional_device<generic_slot_device> m_dock;
optional_device<upd765a_device> m_upd765;
optional_device<floppy_connector> m_upd765_0;
@@ -204,10 +205,7 @@ protected:
optional_ioport m_io_line7;
optional_ioport m_io_nmi;
optional_ioport m_io_config;
- optional_ioport m_io_joy_intf;
- optional_ioport m_io_kempston;
- optional_ioport m_io_fuller;
- optional_ioport m_io_mikrogen;
+
// Plus ports
optional_ioport m_io_plus0;
optional_ioport m_io_plus1;
@@ -215,6 +213,10 @@ protected:
optional_ioport m_io_plus3;
optional_ioport m_io_plus4;
+ // Joystick ports
+ optional_ioport m_io_joy1;
+ optional_ioport m_io_joy2;
+
void spectrum_UpdateBorderBitmap();
void spectrum_UpdateScreenBitmap(bool eof = false);
inline unsigned char get_display_color(unsigned char color, int invert);
@@ -253,6 +255,7 @@ protected:
/*----------- defined in drivers/spectrum.c -----------*/
INPUT_PORTS_EXTERN( spectrum );
+INPUT_PORTS_EXTERN( spec128 );
INPUT_PORTS_EXTERN( spec_plus );
MACHINE_CONFIG_EXTERN( spectrum );