summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus
diff options
context:
space:
mode:
author Nigel Barnes <Pernod70@users.noreply.github.com>2019-11-05 21:19:29 +0000
committer Nigel Barnes <Pernod70@users.noreply.github.com>2019-11-06 11:49:38 +0000
commit71f101d9a7657dfa75fd64a942ff1ee803b6b0e7 (patch)
treebb466147fd021573cdf4503e37204bbfcc7130de /src/devices/bus
parent9f5f84272ecec6486a998cff6e46fdad9b73ae61 (diff)
bbcb: Added many internal ROM/RAM expansion boards from Aries, ATPL, Computech, Peartree, Solidisk, and Watford Electronics.
bbcbp: Added ATPL Sidewise+ internal expansion board. bbcm: Added Morley Master 'AA' and Vine Micros Overlay internal expansion boards.
Diffstat (limited to 'src/devices/bus')
-rw-r--r--src/devices/bus/bbc/internal/aries.cpp337
-rw-r--r--src/devices/bus/bbc/internal/aries.h117
-rw-r--r--src/devices/bus/bbc/internal/atpl.cpp250
-rw-r--r--src/devices/bus/bbc/internal/atpl.h85
-rw-r--r--src/devices/bus/bbc/internal/cumana68k.cpp330
-rw-r--r--src/devices/bus/bbc/internal/cumana68k.h93
-rw-r--r--src/devices/bus/bbc/internal/integrab.cpp342
-rw-r--r--src/devices/bus/bbc/internal/integrab.h67
-rw-r--r--src/devices/bus/bbc/internal/internal.cpp46
-rw-r--r--src/devices/bus/bbc/internal/morleyaa.cpp307
-rw-r--r--src/devices/bus/bbc/internal/morleyaa.h54
-rw-r--r--src/devices/bus/bbc/internal/overlay.cpp224
-rw-r--r--src/devices/bus/bbc/internal/overlay.h57
-rw-r--r--src/devices/bus/bbc/internal/peartree.cpp295
-rw-r--r--src/devices/bus/bbc/internal/peartree.h116
-rw-r--r--src/devices/bus/bbc/internal/ramamp.cpp155
-rw-r--r--src/devices/bus/bbc/internal/ramamp.h55
-rw-r--r--src/devices/bus/bbc/internal/raven20.cpp112
-rw-r--r--src/devices/bus/bbc/internal/raven20.h52
-rw-r--r--src/devices/bus/bbc/internal/romex.cpp134
-rw-r--r--src/devices/bus/bbc/internal/romex.h53
-rw-r--r--src/devices/bus/bbc/internal/stl2m128.cpp248
-rw-r--r--src/devices/bus/bbc/internal/stl2m128.h59
-rw-r--r--src/devices/bus/bbc/internal/stl4m32.cpp303
-rw-r--r--src/devices/bus/bbc/internal/stl4m32.h67
-rw-r--r--src/devices/bus/bbc/internal/stlswr.cpp192
-rw-r--r--src/devices/bus/bbc/internal/stlswr.h108
-rw-r--r--src/devices/bus/bbc/internal/we32kram.cpp142
-rw-r--r--src/devices/bus/bbc/internal/we32kram.h55
-rw-r--r--src/devices/bus/bbc/internal/werom.cpp260
-rw-r--r--src/devices/bus/bbc/internal/werom.h90
-rw-r--r--src/devices/bus/bbc/internal/weromram.cpp133
-rw-r--r--src/devices/bus/bbc/internal/weromram.h58
33 files changed, 4996 insertions, 0 deletions
diff --git a/src/devices/bus/bbc/internal/aries.cpp b/src/devices/bus/bbc/internal/aries.cpp
new file mode 100644
index 00000000000..6bda361d7bd
--- /dev/null
+++ b/src/devices/bus/bbc/internal/aries.cpp
@@ -0,0 +1,337 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Aries B12 Sideways ROM Expansion
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Aries_B12.html
+
+ Aries B20 20K RAM expansion
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Aries_B20.html
+
+ Aries-B32 32K RAM expansion
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Aries_B32.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "aries.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_ARIESB12, bbc_ariesb12_device, "bbc_ariesb12", "Aries-B12 ROM Expansion");
+DEFINE_DEVICE_TYPE(BBC_ARIESB20, bbc_ariesb20_device, "bbc_ariesb20", "Aries-B20 RAM expansion (w/ Aries-B12)");
+DEFINE_DEVICE_TYPE(BBC_ARIESB32, bbc_ariesb32_device, "bbc_ariesb32", "Aries-B32 RAM expansion (w/ Aries-B12)");
+
+
+//-------------------------------------------------
+// ROM( aries )
+//-------------------------------------------------
+
+ROM_START(ariesb20)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_SYSTEM_BIOS(0, "24", "v2.4")
+ ROMX_LOAD("aries-b20_v2.4.rom", 0x0000, 0x2000, CRC(47a43a03) SHA1(2590596e0864b97b30050c33b21aa89bb8956204), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "22", "v2.2")
+ ROMX_LOAD("aries-b20_v2.2.rom", 0x0000, 0x2000, CRC(c2f334a9) SHA1(d04bfd332d63f6f23dca2ef81a1d2074e3d88ee9), ROM_BIOS(1))
+ROM_END
+
+ROM_START(ariesb32)
+ ROM_REGION(0x4000, "aries_rom", 0)
+ ROM_SYSTEM_BIOS(0, "22", "v2.2")
+ ROMX_LOAD("aries-b32_v2.2.rom", 0x0000, 0x4000, CRC(2cb3443d) SHA1(466e3b68f1a8e0287ae095cb3c16dac6afc89dcb), ROM_BIOS(0))
+ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_ariesb12_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot0-3 are unavailable when board is fitted, replaced by sockets on board */;
+ //config.device_remove(":romslot0");
+ //config.device_remove(":romslot1");
+ //config.device_remove(":romslot2");
+ //config.device_remove(":romslot3");
+
+ /* rom/ram sockets */
+ BBC_ROMSLOT16(config, m_rom[0], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[1], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[3], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+}
+
+void bbc_ariesb32_device::device_add_mconfig(machine_config &config)
+{
+ bbc_ariesb12_device::device_add_mconfig(config);
+
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, nullptr);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_ariesb20_device::device_rom_region() const
+{
+ return ROM_NAME(ariesb20);
+}
+
+const tiny_rom_entry *bbc_ariesb32_device::device_rom_region() const
+{
+ return ROM_NAME(ariesb32);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_aries_device - constructor
+//-------------------------------------------------
+
+bbc_ariesb12_device::bbc_ariesb12_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+bbc_ariesb12_device::bbc_ariesb12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_ariesb12_device(mconfig, BBC_ARIESB12, tag, owner, clock)
+{
+}
+
+bbc_ariesb20_device::bbc_ariesb20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_ariesb12_device(mconfig, BBC_ARIESB20, tag, owner, clock)
+{
+}
+
+bbc_ariesb32_device::bbc_ariesb32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_ariesb12_device(mconfig, BBC_ARIESB32, tag, owner, clock)
+ , m_aries_rom(*this, "aries_rom")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_ariesb12_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x24000, m_region_swr->base(), 0x10000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+void bbc_ariesb20_device::device_start()
+{
+ bbc_ariesb12_device::device_start();
+
+ m_shadow = false;
+ m_ram = std::make_unique<uint8_t[]>(0x5000);
+
+ /* register for save states */
+ save_item(NAME(m_shadow));
+ save_pointer(NAME(m_ram), 0x5000);
+}
+
+void bbc_ariesb32_device::device_start()
+{
+ bbc_ariesb12_device::device_start();
+
+ m_shadow = false;
+ m_ram = std::make_unique<uint8_t[]>(0x8000);
+
+ /* move internal roms to board */
+ memcpy(m_region_swr->base() + 0x3c000, m_aries_rom->base(), 0x4000);
+
+ /* register for save states */
+ save_item(NAME(m_ramsel));
+ save_item(NAME(m_shadow));
+ save_pointer(NAME(m_ram), 0x8000);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bbc_ariesb20_device::device_reset()
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ program.install_write_handler(0xfffe, 0xffff, write8sm_delegate(*this, FUNC(bbc_ariesb20_device::control_w)));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_ariesb12_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+
+ return data;
+}
+
+void bbc_ariesb12_device::paged_w(offs_t offset, uint8_t data)
+{
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+
+ /* always write to sideways ram */
+ m_rom[0x00]->write(offset, data);
+}
+
+
+void bbc_ariesb20_device::control_w(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0:
+ /* &fffe - select BBC ram */
+ m_shadow = false;
+ break;
+ case 1:
+ /* &ffff - select Aries ram */
+ m_shadow = true;
+ break;
+ }
+}
+
+uint8_t bbc_ariesb20_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_shadow && offset >= 0x3000)
+ data = m_ram[offset - 0x3000];
+ else
+ data = m_mb_ram->pointer()[offset];
+
+ return data;
+}
+
+void bbc_ariesb20_device::ram_w(offs_t offset, uint8_t data)
+{
+ if (m_shadow && offset >= 0x3000)
+ m_ram[offset - 0x3000] = data;
+ else
+ m_mb_ram->pointer()[offset] = data;
+}
+
+
+void bbc_ariesb32_device::romsel_w(offs_t offset, uint8_t data)
+{
+ //logerror("romsel_w: %04x = %02x\n", offset | 0xfe30, data);
+
+ switch (offset)
+ {
+ case 0x00:
+ m_romsel = data & 0x0f;
+ break;
+ case 0x02:
+ m_ramsel = data & 0x0f;
+ break;
+ case 0x04:
+ break;
+ case 0x06:
+ // switch
+ break;
+ case 0x08:
+ break;
+ case 0x0a:
+ // switch
+ break;
+ case 0x0e:
+ m_shadow = false;
+ break;
+ case 0x0f:
+ m_shadow = true;
+ break;
+ }
+}
+
+uint8_t bbc_ariesb32_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_shadow && offset >= 0x3000)
+ data = m_ram[offset - 0x3000];
+ else
+ data = m_mb_ram->pointer()[offset];
+
+ return data;
+}
+
+void bbc_ariesb32_device::ram_w(offs_t offset, uint8_t data)
+{
+ //if ((offset & 0xff) == 0x00)
+ // logerror("ram_w: %04x = %02x\n", offset, data);
+ if (m_shadow && offset >= 0x3000)
+ m_ram[offset - 0x3000] = data;
+ else
+ m_mb_ram->pointer()[offset] = data;
+}
+
+uint8_t bbc_ariesb32_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else if (m_romsel == 13 || m_romsel == 14)
+ {
+ data = m_ram[offset | (m_romsel & 0x02) << 13];
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+
+ return data;
+}
+
+void bbc_ariesb32_device::paged_w(offs_t offset, uint8_t data)
+{
+ //if ((offset & 0xff) == 0x00)
+ // logerror("paged_w: %04x = %02x\n", offset | 0x8000, data);
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+
+ if (m_ramsel == 13 || m_ramsel == 14)
+ {
+ m_ram[offset | (m_ramsel & 0x02) << 13] = data;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/aries.h b/src/devices/bus/bbc/internal/aries.h
new file mode 100644
index 00000000000..9dc7383ff21
--- /dev/null
+++ b/src/devices/bus/bbc/internal/aries.h
@@ -0,0 +1,117 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Aries B12 Sideways ROM Expansion
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Aries_B12.html
+
+ Aries B20 20K RAM expansion
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Aries_B20.html
+
+ Aries-B32 32K RAM expansion
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Aries_B32.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_ARIES_H
+#define MAME_BUS_BBC_INTERNAL_ARIES_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_ariesb12_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_ariesb12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_ariesb12_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ uint8_t m_romsel;
+};
+
+
+class bbc_ariesb20_device : public bbc_ariesb12_device
+{
+public:
+ // construction/destruction
+ bbc_ariesb20_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 bool overrides_ram() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+
+private:
+ void control_w(offs_t offset, uint8_t data);
+
+ bool m_shadow;
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+
+class bbc_ariesb32_device : public bbc_ariesb12_device
+{
+public:
+ // construction/destruction
+ bbc_ariesb32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual bool overrides_ram() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+ virtual void romsel_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_memory_region m_aries_rom;
+
+ bool m_shadow;
+ std::unique_ptr<uint8_t[]> m_ram;
+ uint8_t m_ramsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_ARIESB12, bbc_ariesb12_device);
+DECLARE_DEVICE_TYPE(BBC_ARIESB20, bbc_ariesb20_device);
+DECLARE_DEVICE_TYPE(BBC_ARIESB32, bbc_ariesb32_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_ARIES_H */
diff --git a/src/devices/bus/bbc/internal/atpl.cpp b/src/devices/bus/bbc/internal/atpl.cpp
new file mode 100644
index 00000000000..94c5f8459b0
--- /dev/null
+++ b/src/devices/bus/bbc/internal/atpl.cpp
@@ -0,0 +1,250 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ATPL Sidewise ROM/RAM Expansion board
+ https://www.retro-kit.co.uk/page.cfm/content/ATPL-Sidewise-Sideways-ROM-board/
+
+ ATPL Sidewise+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/ATPL_Sidewise+.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "atpl.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_ATPLSW, bbc_atplsw_device, "bbc_atplsw", "ATPL Sidewise ROM/RAM Expansion");
+DEFINE_DEVICE_TYPE(BBC_ATPLSWP, bbc_atplswp_device, "bbc_atplswp", "ATPL Sidewise+ ROM Expansion");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( atplsw )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(atplsw)
+ PORT_START("wp")
+ PORT_CONFNAME(0x01, 0x00, "Write Protect Sideways RAM")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_atplsw_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(atplsw);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_atplsw_device::device_add_mconfig(machine_config &config)
+{
+ /* 12 rom sockets, 16K static ram (battery backed) */
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "nvram").set_fixed_ram(true);
+}
+
+void bbc_atplswp_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot2-10 are unavailable when board is fitted, replaced by sockets on board */
+ //config.device_remove(":romslot2");
+ //config.device_remove(":romslot4");
+ //config.device_remove(":romslot6");
+ //config.device_remove(":romslot8");
+ //config.device_remove(":romslot10");
+
+ /* 10 rom sockets */
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[3], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_atplsw_device - constructor
+//-------------------------------------------------
+
+bbc_atplsw_device::bbc_atplsw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_ATPLSW, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+ , m_wp(*this, "wp")
+{
+}
+
+bbc_atplswp_device::bbc_atplswp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_ATPLSWP, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_atplsw_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x2c000, m_region_swr->base(), 0x10000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+void bbc_atplswp_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_atplsw_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_atplsw_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+
+ /* sideways ram (if not write protected) */
+ if (!m_wp->read())
+ {
+ m_rom[15]->write(offset, data);
+ }
+}
+
+
+uint8_t bbc_atplswp_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 12: case 13:
+ /* motherboard ram sockets */
+ if (m_mb_rom[m_romsel & 0x0e] && m_mb_rom[m_romsel & 0x0e]->present())
+ {
+ data = m_mb_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_atplswp_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 12: case 13:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel & 0x0e])
+ {
+ m_mb_rom[m_romsel & 0x0e]->write(offset | (m_romsel & 0x01) << 14, data);
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/atpl.h b/src/devices/bus/bbc/internal/atpl.h
new file mode 100644
index 00000000000..fe10ebb3a76
--- /dev/null
+++ b/src/devices/bus/bbc/internal/atpl.h
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ATPL Sidewise ROM/RAM Expansion board
+ https://www.retro-kit.co.uk/page.cfm/content/ATPL-Sidewise-Sideways-ROM-board/
+
+ ATPL Sidewise+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/ATPL_Sidewise+.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_ATPL_H
+#define MAME_BUS_BBC_INTERNAL_ATPL_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_atplsw_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_atplsw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+ required_ioport m_wp;
+
+ uint8_t m_romsel;
+};
+
+
+class bbc_atplswp_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_atplswp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ uint8_t m_romsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_ATPLSW, bbc_atplsw_device);
+DECLARE_DEVICE_TYPE(BBC_ATPLSWP, bbc_atplswp_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_ATPL_H */
diff --git a/src/devices/bus/bbc/internal/cumana68k.cpp b/src/devices/bus/bbc/internal/cumana68k.cpp
new file mode 100644
index 00000000000..92daaca46b4
--- /dev/null
+++ b/src/devices/bus/bbc/internal/cumana68k.cpp
@@ -0,0 +1,330 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Cumana 68008 2nd processor
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Cumana_680082ndProcessor.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "cumana68k.h"
+#include "bus/scsi/scsihd.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_CUMANA68K, bbc_cumana68k_device, "bbc_cumana68k", "Cumana 68008 2nd Processor")
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( cumana68k_mem )
+//-------------------------------------------------
+
+void bbc_cumana68k_device::cumana68k_mem(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x000000, 0x00ffff).rw(FUNC(bbc_cumana68k_device::dma_r), FUNC(bbc_cumana68k_device::dma_w));
+ map(0x010000, 0x0fffff).ram();
+}
+
+//-------------------------------------------------
+// SLOT_INTERFACE( os9_floppies )
+//-------------------------------------------------
+
+static void os9_floppies(device_slot_interface &device)
+{
+ device.option_add("525qd", FLOPPY_525_QD);
+}
+
+//-------------------------------------------------
+// ROM( cumana68k )
+//-------------------------------------------------
+
+ROM_START(cumana68k)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_LOAD("os9boot.rom", 0x0000, 0x4000, CRC(9b7d6754) SHA1(1cb54119bf13b39d598573d8d6a7e9f70d88b50d))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_cumana68k_device::device_add_mconfig(machine_config &config)
+{
+ /* basic machine hardware */
+ M68008(config, m_m68008, 16_MHz_XTAL / 2);
+ m_m68008->set_addrmap(AS_PROGRAM, &bbc_cumana68k_device::cumana68k_mem);
+ //m_m68008->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(bbc_cumana68k_device::irq_callback), this));
+
+ /* fdc */
+ WD2797(config, m_fdc, 16_MHz_XTAL / 16);
+ m_fdc->intrq_wr_callback().set(m_pia_rtc, FUNC(pia6821_device::cb1_w));
+ m_fdc->drq_wr_callback().set(FUNC(bbc_cumana68k_device::drq_w));
+ m_fdc->set_force_ready(true);
+
+ FLOPPY_CONNECTOR(config, m_floppy0, os9_floppies, "525qd", floppy_image_device::default_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy1, os9_floppies, "525qd", floppy_image_device::default_floppy_formats).enable_sound(true);
+
+ /* scsi */
+ //MCFG_DEVICE_ADD("sasi", SCSI_PORT, 0)
+ //MCFG_SCSI_DATA_INPUT_BUFFER("scsi_data_in")
+ //MCFG_SCSI_SEL_HANDLER(WRITELINE(*this, bbc_cumana68k_device, write_sasi_sel))
+ //MCFG_SCSI_IO_HANDLER(WRITELINE(*this, bbc_cumana68k_device, write_sasi_io))
+ //MCFG_SCSI_BSY_HANDLER(WRITELINE(*this, bbc_cumana68k_device, write_sasi_bsy))
+ //MCFG_SCSI_CD_HANDLER(WRITELINE(*this, bbc_cumana68k_device, write_sasi_cd))
+ //MCFG_SCSI_MSG_HANDLER(WRITELINE(*this, bbc_cumana68k_device, write_sasi_msg))
+ //MCFG_SCSI_REQ_HANDLER(WRITELINE(*this, bbc_cumana68k_device, write_sasi_req))
+ //MCFG_SCSI_ACK_HANDLER(WRITELINE("pia_sasi", pia6821_device, ca2_w))
+ //MCFG_SCSIDEV_ADD("sasi:" SCSI_PORT_DEVICE1, "harddisk", SCSIHD, SCSI_ID_0)
+
+ //MCFG_SCSI_OUTPUT_LATCH_ADD("scsi_data_out", "sasi")
+ //MCFG_DEVICE_ADD("scsi_data_in", INPUT_BUFFER, 0)
+
+ PIA6821(config, m_pia_sasi, 0);
+ m_pia_sasi->readpa_handler().set(FUNC(bbc_cumana68k_device::pia_sasi_pa_r));
+ m_pia_sasi->readpb_handler().set(FUNC(bbc_cumana68k_device::pia_sasi_pb_r));
+ m_pia_sasi->readcb1_handler().set(FUNC(bbc_cumana68k_device::pia_sasi_cb1_r));
+ //m_pia_sasi->cb2_handler().set(m_scsibus, FUNC(scsi_port_device::write_rst));
+ m_pia_sasi->irqa_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
+ m_pia_sasi->irqb_handler().set(m_irqs, FUNC(input_merger_device::in_w<1>));
+
+ PIA6821(config, m_pia_rtc, 0);
+ m_pia_rtc->readpa_handler().set(m_rtc, FUNC(mc146818_device::read));
+ m_pia_rtc->writepa_handler().set(m_rtc, FUNC(mc146818_device::write));
+ m_pia_rtc->writepb_handler().set(FUNC(bbc_cumana68k_device::pia_rtc_pb_w));
+ //m_pia_rtc->cb2_handler().set(m_scsibus, FUNC(scsi_port_device::write_rst));
+ m_pia_rtc->irqa_handler().set(m_irqs, FUNC(input_merger_device::in_w<2>));
+ m_pia_rtc->irqb_handler().set(m_irqs, FUNC(input_merger_device::in_w<3>));
+
+ INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set(FUNC(bbc_cumana68k_device::intrq_w));
+
+ /* rtc */
+ MC146818(config, m_rtc, 32.768_kHz_XTAL);
+ m_rtc->irq().set(m_pia_rtc, FUNC(pia6821_device::ca1_w));
+
+ /* software lists */
+ SOFTWARE_LIST(config, "flop_ls_68008").set_original("bbc_flop_68008");
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_cumana68k_device::device_rom_region() const
+{
+ return ROM_NAME( cumana68k );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_cumana68k_device - constructor
+//-------------------------------------------------
+
+bbc_cumana68k_device::bbc_cumana68k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_CUMANA68K, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_maincpu(*this, ":maincpu")
+ , m_m68008(*this, "m68008")
+ , m_pia_sasi(*this, "pia_sasi")
+ , m_pia_rtc(*this, "pia_rtc")
+ , m_irqs(*this, "irqs")
+ , m_rtc(*this, "rtc")
+ , m_fdc(*this, "wd2797")
+ , m_floppy0(*this, "wd2797:0")
+ , m_floppy1(*this, "wd2797:1")
+ //, m_scsibus(*this, "sasi")
+ //, m_scsi_data_out(*this, "scsi_data_out")
+ //, m_scsi_data_in(*this, "scsi_data_in")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_cumana68k_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bbc_cumana68k_device::device_reset()
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ program.install_readwrite_handler(0xfc40, 0xfc43, read8sm_delegate(*m_pia_sasi, FUNC(pia6821_device::read)), write8sm_delegate(*m_pia_sasi, FUNC(pia6821_device::write)));
+ program.install_readwrite_handler(0xfc44, 0xfc47, read8sm_delegate(*m_pia_rtc, FUNC(pia6821_device::read)), write8sm_delegate(*m_pia_rtc, FUNC(pia6821_device::write)));
+ program.install_readwrite_handler(0xfc48, 0xfc4b, read8sm_delegate(*m_fdc, FUNC(wd2797_device::read)), write8sm_delegate(*m_fdc, FUNC(wd2797_device::write)));
+}
+
+void bbc_cumana68k_device::device_reset_after_children()
+{
+ m_bEnabled = false;
+
+ // Pull up resistor R12 makes CB2 high when it's configured as an input, so set CB2 as output and high to compensate
+ m_pia_rtc->write(0x03, 0x3c);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+WRITE_LINE_MEMBER(bbc_cumana68k_device::reset68008_w)
+{
+ if (!state) m_bEnabled = true;
+
+ m_m68008->set_input_line(INPUT_LINE_HALT, state);
+ m_m68008->set_input_line(INPUT_LINE_RESET, state);
+}
+
+
+READ8_MEMBER(bbc_cumana68k_device::dma_r)
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ if (m_bEnabled)
+ {
+ if (offset < 0x1000)
+ return program.read_byte(offset + 0x2000);
+ else if (offset > 0x1fff && offset < 0x3000)
+ return program.read_byte(offset - 0x2000);
+ else
+ return program.read_byte(offset);
+ }
+ return 0xff;
+}
+
+WRITE8_MEMBER(bbc_cumana68k_device::dma_w)
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ if (m_bEnabled)
+ {
+ if (offset < 0x1000)
+ program.write_byte(offset + 0x2000, data);
+ else if (offset > 0x1fff && offset < 0x3000)
+ program.write_byte(offset - 0x2000, data);
+ else
+ program.write_byte(offset, data);
+ }
+}
+
+
+WRITE8_MEMBER(bbc_cumana68k_device::pia_rtc_pb_w)
+{
+ floppy_image_device *floppy = nullptr;
+ logerror("pia1_pb_w %02x\n", data);
+ // bit 0, 1: drive select
+ switch (data & 0x03)
+ {
+ case 0: floppy = m_floppy0->get_device(); break;
+ case 1: floppy = m_floppy1->get_device(); break;
+ }
+ m_fdc->set_floppy(floppy);
+
+ // bit 2: motor enable
+ if (floppy)
+ floppy->mon_w(BIT(data, 2));
+
+ // bit 3: density
+ m_fdc->dden_w(BIT(data, 3));
+
+ // bit 4: enable precomp
+}
+
+WRITE_LINE_MEMBER(bbc_cumana68k_device::intrq_w)
+{
+ //m_m68008->set_input_line_and_vector(M68K_IRQ_2, state ? ASSERT_LINE : CLEAR_LINE, M68K_INT_ACK_AUTOVECTOR);
+ m_m68008->set_input_line(M68K_IRQ_2, state);
+ m_slot->irq_w(state);
+}
+
+WRITE_LINE_MEMBER(bbc_cumana68k_device::drq_w)
+{
+ m_pia_sasi_pb &= ~0x40;
+ m_pia_sasi_pb |= state << 6;
+
+ //m_m68008->set_input_line(M68K_IRQ_7, state);
+ m_slot->nmi_w(!state);
+}
+
+
+IRQ_CALLBACK_MEMBER(bbc_cumana68k_device::irq_callback)
+{
+ //m_m68008->set_input_line(M68K_IRQ_2, CLEAR_LINE);
+ // see https://github.com/mamedev/mame/commit/e39802db90860d6628c35265f7c78ce3534f5a53
+ return 0; //M68K_INT_ACK_AUTOVECTOR;
+}
+
+
+WRITE_LINE_MEMBER(bbc_cumana68k_device::write_sasi_sel)
+{
+ m_pia_sasi_pb &= ~0x02;
+ m_pia_sasi_pb |= state << 1;
+}
+
+WRITE_LINE_MEMBER(bbc_cumana68k_device::write_sasi_io)
+{
+ m_pia_sasi_pb &= ~0x04;
+ m_pia_sasi_pb |= state << 2;
+}
+
+WRITE_LINE_MEMBER(bbc_cumana68k_device::write_sasi_bsy)
+{
+ m_pia_sasi_pb &= ~0x08;
+ m_pia_sasi_pb |= state << 3;
+}
+
+WRITE_LINE_MEMBER(bbc_cumana68k_device::write_sasi_cd)
+{
+ m_pia_sasi_pb &= ~0x10;
+ m_pia_sasi_pb |= state << 4;
+}
+
+WRITE_LINE_MEMBER(bbc_cumana68k_device::write_sasi_msg)
+{
+ m_pia_sasi_pb &= ~0x20;
+ m_pia_sasi_pb |= state << 5;
+}
+
+WRITE_LINE_MEMBER(bbc_cumana68k_device::write_sasi_req)
+{
+ m_pia_sasi_pb &= ~0x40;
+ m_pia_sasi_pb |= state << 6;
+
+ m_pia_sasi->ca1_w(state);
+}
+
+
+READ8_MEMBER(bbc_cumana68k_device::pia_sasi_pa_r)
+{
+ return 0; // m_scsi_data_in->read();
+}
+
+WRITE8_MEMBER(bbc_cumana68k_device::pia_sasi_pa_w)
+{
+ //m_scsi_data_out->write(data);
+}
+
+
+READ8_MEMBER(bbc_cumana68k_device::pia_sasi_pb_r)
+{
+ return m_pia_sasi_pb;
+}
+
+READ_LINE_MEMBER(bbc_cumana68k_device::pia_sasi_cb1_r)
+{
+ // CB1 is tied to +5V
+ return 1;
+}
diff --git a/src/devices/bus/bbc/internal/cumana68k.h b/src/devices/bus/bbc/internal/cumana68k.h
new file mode 100644
index 00000000000..067d860acf5
--- /dev/null
+++ b/src/devices/bus/bbc/internal/cumana68k.h
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Cumana 68008 2nd processor
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Cumana_680082ndProcessor.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_CUMANA68K_H
+#define MAME_BUS_BBC_INTERNAL_CUMANA68K_H
+
+#include "internal.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/6821pia.h"
+#include "machine/input_merger.h"
+#include "machine/mc146818.h"
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+#include "bus/scsi/scsi.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_cumana68k_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_cumana68k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_WRITE_LINE_MEMBER(write_sasi_sel);
+ DECLARE_WRITE_LINE_MEMBER(write_sasi_msg);
+ DECLARE_WRITE_LINE_MEMBER(write_sasi_bsy);
+ DECLARE_WRITE_LINE_MEMBER(write_sasi_req);
+ DECLARE_WRITE_LINE_MEMBER(write_sasi_io);
+ DECLARE_WRITE_LINE_MEMBER(write_sasi_cd);
+ DECLARE_READ8_MEMBER(pia_sasi_pa_r);
+ DECLARE_WRITE8_MEMBER(pia_sasi_pa_w);
+ DECLARE_READ8_MEMBER(pia_sasi_pb_r);
+ DECLARE_READ_LINE_MEMBER(pia_sasi_cb1_r);
+ DECLARE_WRITE8_MEMBER(pia_rtc_pb_w);
+
+ DECLARE_READ8_MEMBER(dma_r);
+ DECLARE_WRITE8_MEMBER(dma_w);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_reset_after_children() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ DECLARE_WRITE_LINE_MEMBER(intrq_w);
+ DECLARE_WRITE_LINE_MEMBER(drq_w);
+ DECLARE_WRITE_LINE_MEMBER(reset68008_w);
+ IRQ_CALLBACK_MEMBER(irq_callback);
+
+ required_device<cpu_device> m_maincpu;
+ required_device<m68000_base_device> m_m68008;
+ required_device<pia6821_device> m_pia_sasi;
+ required_device<pia6821_device> m_pia_rtc;
+ required_device<input_merger_device> m_irqs;
+ required_device<mc146818_device> m_rtc;
+ required_device<wd2797_device> m_fdc;
+ required_device<floppy_connector> m_floppy0;
+ optional_device<floppy_connector> m_floppy1;
+ //required_device<scsi_port_device> m_scsibus;
+ //required_device<output_latch_device> m_scsi_data_out;
+ //required_device<input_buffer_device> m_scsi_data_in;
+
+ void cumana68k_mem(address_map &map);
+
+ bool m_bEnabled;
+ int m_fdc_ie;
+ int m_fdc_drq;
+ uint8_t m_pia_sasi_pb;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_CUMANA68K, bbc_cumana68k_device)
+
+
+#endif // MAME_BUS_BBC_INTERNAL_CUMANA68K_H
diff --git a/src/devices/bus/bbc/internal/integrab.cpp b/src/devices/bus/bbc/internal/integrab.cpp
new file mode 100644
index 00000000000..0bba0add02c
--- /dev/null
+++ b/src/devices/bus/bbc/internal/integrab.cpp
@@ -0,0 +1,342 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computech Integra-B expansion board
+
+ Usage:
+ To enable the computer to acknowledge the INTEGRA-β Expansion on the
+ first switch-on you must hold down the '@' key whilst switching on
+ the computer, or CTRL-@-BREAK to reset.
+
+ If default language has not been configured then reset the board and:
+ *CONFIGURE LANG 14
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "integrab.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_INTEGRAB, bbc_integrab_device, "bbc_integrab", "Computech Integra-\xCE\xB2")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( integrab )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(integrab)
+ PORT_START("wp")
+ PORT_CONFNAME(0x01, 0x00, "Write Protect Sideways RAM Banks 4/5")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+ PORT_CONFNAME(0x02, 0x00, "Write Protect Sideways RAM Bank 6/7")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x02, DEF_STR(Yes))
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_integrab_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(integrab);
+}
+
+//-------------------------------------------------
+// ROM( integrab )
+//-------------------------------------------------
+
+ROM_START(integrab)
+ ROM_REGION(0x4000, "ibos", 0)
+ ROM_SYSTEM_BIOS(0, "120p", "IBOS 1.20 (Y2K patched)")
+ ROMX_LOAD("ibos120p.rom", 0x0000, 0x4000, CRC(21e7a2c2) SHA1(d5ff79da2243aabd363ee26a1e7ad546657fdeb5), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "120", "IBOS 1.20")
+ ROMX_LOAD("ibos120.rom", 0x0000, 0x4000, CRC(52b1b8c4) SHA1(0f5b2a5bee23808b34eab2f027f7c1e77395c782), ROM_BIOS(1))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_integrab_device::device_add_mconfig(machine_config &config)
+{
+ /* rtc */
+ MC146818(config, m_rtc, 32.768_kHz_XTAL); // CDP6818
+ m_rtc->irq().set(DEVICE_SELF_OWNER, FUNC(bbc_internal_slot_device::irq_w));
+
+ /* rom/ram sockets */
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, nullptr);
+
+ /* battery-backed ram */
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_integrab_device::device_rom_region() const
+{
+ return ROM_NAME( integrab );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_integrab_device - constructor
+//-------------------------------------------------
+
+bbc_integrab_device::bbc_integrab_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_INTEGRAB, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_ibos(*this, "ibos")
+ , m_rom(*this, "romslot%u", 0U)
+ , m_nvram(*this, "nvram")
+ , m_rtc(*this, "rtc")
+ , m_wp(*this, "wp")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_integrab_device::device_start()
+{
+ m_shadow = false;
+ m_ram = std::make_unique<uint8_t[]>(0x8000);
+ m_nvram->set_base(m_ram.get(), 0x8000);
+
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x2c000, m_region_swr->base(), 0x10000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+ memcpy(m_region_swr->base() + 0x3c000, m_ibos->base(), 0x4000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_ramsel));
+ save_item(NAME(m_shadow));
+ save_pointer(NAME(m_ram), 0x8000);
+}
+
+void bbc_integrab_device::device_reset()
+{
+ m_romsel = 0;
+ m_ramsel = 0;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_integrab_device::romsel_r(offs_t offset)
+{
+ uint8_t data = 0xfe;
+
+ switch (offset & 0x0c)
+ {
+ case 0x08:
+ data = m_rtc->read(0);
+ break;
+ case 0x0c:
+ data = m_rtc->read(1);
+ break;
+ }
+
+ return data;
+}
+
+void bbc_integrab_device::romsel_w(offs_t offset, uint8_t data)
+{
+ /*
+ ROMSEL & ROMID
+ Bits 0,3 ROMNUM Sideways ROM/RAM select bits
+ Bits 4,5 Not used
+ Bit 6 PRVEN Private RAM enable
+ Bit 7 MEMSEL Shadow/Main RAM toggle
+
+ RAMSEL & RAMID
+ Bits 0,1 AUX0,1 Not used but must be preserved
+ Bits 2,3 Not used
+ Bit 4 PRVS8 Private RAM 8K area select (&9000-&AFFF)
+ Bit 5 PRVS4 Private RAM 4K area select (&8000-&8FFF)
+ Bit 6 PRVS1 Private RAM 1K area select (&8000-&83FF)
+ Bit 7 SHEN Shadow RAM enable bit
+ */
+ switch (offset & 0x0c)
+ {
+ case 0x00:
+ m_romsel = data;
+ break;
+ case 0x04:
+ m_ramsel = data;
+ break;
+ case 0x08:
+ m_rtc->write(0, data);
+ break;
+ case 0x0c:
+ m_rtc->write(1, data);
+ break;
+ }
+
+ m_shadow = BIT(m_ramsel, 7) && !BIT(m_romsel, 7);
+}
+
+uint8_t bbc_integrab_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_shadow && offset >= 0x3000)
+ data = m_ram[offset];
+ else
+ data = m_mb_ram->pointer()[offset];
+
+ return data;
+}
+
+void bbc_integrab_device::ram_w(offs_t offset, uint8_t data)
+{
+ if (m_shadow && offset >= 0x3000)
+ m_ram[offset] = data;
+ else
+ m_mb_ram->pointer()[offset] = data;
+}
+
+uint8_t bbc_integrab_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+ uint8_t romsel = m_romsel & 0x0f;
+
+ switch (romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[romsel] && m_mb_rom[romsel]->present())
+ {
+ data = m_mb_rom[romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (romsel << 14)];
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ /* expansion board sockets */
+ if (m_rom[romsel] && m_rom[romsel]->present())
+ {
+ data = m_rom[romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (romsel << 14)];
+ }
+ break;
+ }
+
+ /* private ram */
+ if (BIT(m_romsel, 6))
+ {
+ switch (offset & 0x3c00)
+ {
+ case 0x0000:
+ /* PRVS1 */
+ if (m_ramsel & 0x60)
+ data = m_ram[offset];
+ break;
+ case 0x0400: case 0x0800: case 0x0c00:
+ /* PRVS4 */
+ if (m_ramsel & 0x20)
+ data = m_ram[offset];
+ break;
+ case 0x1000: case 0x1400: case 0x1800: case 0x1c00: case 0x2000: case 0x2400: case 0x2800: case 0x2c00:
+ /* PRVS8 */
+ if (m_ramsel & 0x10)
+ data = m_ram[offset];
+ break;
+ }
+ }
+
+ return data;
+}
+
+void bbc_integrab_device::paged_w(offs_t offset, uint8_t data)
+{
+ uint8_t romsel = m_romsel & 0x0f;
+
+ /* private ram */
+ if (BIT(m_romsel, 6))
+ {
+ switch (offset & 0x3c00)
+ {
+ case 0x0000:
+ /* PRVS1 */
+ if (m_ramsel & 0x60)
+ m_ram[offset] = data;
+ break;
+ case 0x0400: case 0x0800: case 0x0c00:
+ /* PRVS4 */
+ if (m_ramsel & 0x20)
+ m_ram[offset] = data;
+ break;
+ case 0x1000: case 0x1400: case 0x1800: case 0x1c00: case 0x2000: case 0x2400: case 0x2800: case 0x2c00:
+ /* PRVS8 */
+ if (m_ramsel & 0x10)
+ m_ram[offset] = data;
+ break;
+ }
+ }
+ else
+ {
+ switch (romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[romsel])
+ {
+ m_mb_rom[romsel]->write(offset, data);
+ }
+ break;
+ case 4: case 5:
+ /* expansion board sockets */
+ if (m_rom[romsel] && !BIT(m_wp->read(), 0))
+ {
+ m_rom[romsel]->write(offset, data);
+ }
+ break;
+ case 6: case 7:
+ /* expansion board sockets */
+ if (m_rom[romsel] && !BIT(m_wp->read(), 1))
+ {
+ m_rom[romsel]->write(offset, data);
+ }
+ break;
+ case 8: case 9: case 10: case 11: case 12: case 13: case 14:
+ /* expansion board sockets */
+ if (m_rom[romsel])
+ {
+ m_rom[romsel]->write(offset, data);
+ }
+ break;
+ }
+ }
+}
diff --git a/src/devices/bus/bbc/internal/integrab.h b/src/devices/bus/bbc/internal/integrab.h
new file mode 100644
index 00000000000..679bdc44526
--- /dev/null
+++ b/src/devices/bus/bbc/internal/integrab.h
@@ -0,0 +1,67 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computech Integra-B expansion board
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_INTEGRAB_H
+#define MAME_BUS_BBC_INTERNAL_INTEGRAB_H
+
+#include "internal.h"
+#include "machine/mc146818.h"
+#include "machine/nvram.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_integrab_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_integrab_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 const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual bool overrides_ram() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t romsel_r(offs_t offset) override;
+ virtual void romsel_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_memory_region m_ibos;
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+ required_device<nvram_device> m_nvram;
+ required_device<mc146818_device> m_rtc;
+ required_ioport m_wp;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+ bool m_shadow;
+ uint8_t m_romsel;
+ uint8_t m_ramsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_INTEGRAB, bbc_integrab_device)
+
+
+#endif // MAME_BUS_BBC_INTERNAL_INTEGRAB_H
diff --git a/src/devices/bus/bbc/internal/internal.cpp b/src/devices/bus/bbc/internal/internal.cpp
index ca179bec25d..98651b23e31 100644
--- a/src/devices/bus/bbc/internal/internal.cpp
+++ b/src/devices/bus/bbc/internal/internal.cpp
@@ -153,16 +153,62 @@ void bbc_internal_slot_device::latch_fe60_w(uint8_t data)
// slot devices
+#include "aries.h"
+#include "atpl.h"
+#include "cumana68k.h"
+#include "integrab.h"
+#include "morleyaa.h"
+#include "overlay.h"
+#include "peartree.h"
+#include "ramamp.h"
+#include "raven20.h"
+//#include "replaym.h"
+#include "romex.h"
+#include "stlswr.h"
+#include "stl2m128.h"
+#include "stl4m32.h"
+//#include "stl4m256.h"
+#include "werom.h"
+#include "weromram.h"
+#include "we32kram.h"
void bbcb_internal_devices(device_slot_interface &device)
{
+ device.option_add("ariesb12", BBC_ARIESB12); /* Aries-B12 ROM expansion */
+ device.option_add("ariesb20", BBC_ARIESB20); /* Aries-B20 RAM expansion */
+ device.option_add("ariesb32", BBC_ARIESB32); /* Aries-B32 RAM expansion */
+ device.option_add("atplsw", BBC_ATPLSW); /* ATPL Sidewise ROM/RAM expansion */
+ device.option_add("cumana68k", BBC_CUMANA68K); /* Cumana 68008 2nd Processor */
+ device.option_add("integrab", BBC_INTEGRAB); /* Computech Integra-B */
+ device.option_add("mr3000", BBC_MR3000); /* Peartree MR3000 ROM board */
+ device.option_add("mr4200", BBC_MR4200); /* Peartree MR4200 RAM board */
+ device.option_add("mr4300", BBC_MR4300); /* Peartree MR4300 ROM/RAM board */
+ device.option_add("mr4800", BBC_MR4800); /* Peartree MR4800 RAM board */
+ device.option_add("ramamp", BBC_RAMAMP); /* Ramamp Sideways RAM/ROM board */
+ device.option_add("raven20", BBC_RAVEN20); /* Raven-20 RAM expansion */
+ device.option_add("romex13", BBC_ROMEX13); /* GCC Romex13 ROM expansion */
+ device.option_add("swr16", BBC_STLSWR16); /* Solidisk SWR16 */
+ device.option_add("swr32", BBC_STLSWR32); /* Solidisk SWR32 */
+ device.option_add("swr64", BBC_STLSWR64); /* Solidisk SWR64 */
+ device.option_add("swr128", BBC_STLSWR128); /* Solidisk SWR128 */
+ device.option_add("2m128", BBC_STL2M128); /* Solidisk Twomeg 128 */
+ device.option_add("4m32", BBC_STL4M32); /* Solidisk Fourmeg 32 */
+ //device.option_add("4m256", BBC_STL4M256); /* Solidisk Fourmeg 256 */
+ device.option_add("we12rom", BBC_WE12ROM); /* Watford Electronics 12 ROM board */
+ device.option_add("we13rom", BBC_WE13ROM); /* Watford Electronics 13 ROM board */
+ device.option_add("weromram", BBC_WEROMRAM); /* Watford Electronics RAM/ROM board */
+ device.option_add("we32kram", BBC_WE32KRAM); /* Watford Electronics 32K Shadow RAM */
}
void bbcbp_internal_devices(device_slot_interface &device)
{
+ device.option_add("atplswp", BBC_ATPLSWP); /* ATPL Sidewise+ ROM expansion */
}
void bbcm_internal_devices(device_slot_interface &device)
{
+ device.option_add("morleyaa", BBC_MORLEYAA); /* Morley Master Board 'AA' */
+ device.option_add("overlay", BBC_OVERLAY); /* Vine Micros OS Overlay Board */
+ //device.option_add("replaym", BBC_REPLAYM); /* Vine Micros Master Replay */
}
diff --git a/src/devices/bus/bbc/internal/morleyaa.cpp b/src/devices/bus/bbc/internal/morleyaa.cpp
new file mode 100644
index 00000000000..e01336c3b5c
--- /dev/null
+++ b/src/devices/bus/bbc/internal/morleyaa.cpp
@@ -0,0 +1,307 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Morley Electronics 'AA' Master ROM Expansion Board
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "morleyaa.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_MORLEYAA, bbc_morleyaa_device, "bbc_morleyaa", "Morley Electronics 'AA' Master ROM Expansion Board");
+
+
+//-------------------------------------------------
+// ROM( morleyaa )
+//-------------------------------------------------
+
+ROM_START(morleyaa)
+ ROM_REGION(0x4000, "aa_rom", 0)
+ ROM_LOAD("masterboard_200.rom", 0x0000, 0x4000, CRC(d93738ec) SHA1(c80f47e3f661b1636d21ff542c7a39a586008098))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_morleyaa_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot0-3 are unavailable when board is fitted, replaced by sockets on board */;
+ //config.device_remove(":romslot8");
+
+ /* 8 x 16K rom sockets */
+ BBC_ROMSLOT16(config, m_rom[0], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[1], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[3], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ /* 4 x 32K rom sockets */
+ BBC_ROMSLOT32(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[11], bbc_rom_devices, nullptr);
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_morleyaa_device::device_rom_region() const
+{
+ return ROM_NAME(morleyaa);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_morleyaa_device - constructor
+//-------------------------------------------------
+
+bbc_morleyaa_device::bbc_morleyaa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_MORLEYAA, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_aa_rom(*this, "aa_rom")
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_morleyaa_device::device_start()
+{
+ /* move internal roms to board */
+ memcpy(m_region_swr->base() + 0x20000, m_aa_rom->base(), 0x4000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_banksel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_morleyaa_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 8:
+ data = m_aa_rom->base()[offset];
+ break;
+ case 4:
+ if (m_banksel & 0x20)
+ {
+ /* motherboard ram selected */
+ data = m_mb_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ switch (m_banksel & 0x07)
+ {
+ case 2:
+ data = m_rom[0]->read(offset);
+ break;
+ case 4:
+ data = m_rom[2]->read(offset);
+ break;
+ case 0:
+ data = m_rom[4]->read(offset);
+ break;
+ case 6:
+ data = m_rom[6]->read(offset);
+ break;
+ case 7:
+ data = m_rom[8]->read(offset);
+ break;
+ case 3:
+ data = m_rom[9]->read(offset);
+ break;
+ case 5:
+ data = m_rom[10]->read(offset);
+ break;
+ case 1:
+ data = m_rom[11]->read(offset);
+ break;
+ }
+ }
+ break;
+ case 5:
+ if (m_banksel & 0x20)
+ {
+ /* motherboard ram selected */
+ data = m_mb_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ switch (m_banksel & 0x07)
+ {
+ case 2:
+ data = m_rom[1]->read(offset);
+ break;
+ case 4:
+ data = m_rom[3]->read(offset);
+ break;
+ case 0:
+ data = m_rom[5]->read(offset);
+ break;
+ case 6:
+ data = m_rom[7]->read(offset);
+ break;
+ case 7:
+ data = m_rom[8]->read(offset | 0x4000);
+ break;
+ case 3:
+ data = m_rom[9]->read(offset | 0x4000);
+ break;
+ case 5:
+ data = m_rom[10]->read(offset | 0x4000);
+ break;
+ case 1:
+ data = m_rom[11]->read(offset | 0x4000);
+ break;
+ }
+ }
+ break;
+ case 6:
+ if (m_banksel & 0x40)
+ {
+ /* motherboard ram selected */
+ data = m_mb_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ switch (bitswap<8>(m_banksel, 2, 6, 5, 0, 1, 7, 3, 4) & 0x07)
+ {
+ case 2:
+ data = m_rom[0]->read(offset);
+ break;
+ case 4:
+ data = m_rom[2]->read(offset);
+ break;
+ case 0:
+ data = m_rom[4]->read(offset);
+ break;
+ case 6:
+ data = m_rom[6]->read(offset);
+ break;
+ case 7:
+ data = m_rom[8]->read(offset);
+ break;
+ case 3:
+ data = m_rom[9]->read(offset);
+ break;
+ case 5:
+ data = m_rom[10]->read(offset);
+ break;
+ case 1:
+ data = m_rom[11]->read(offset);
+ break;
+ }
+ }
+ break;
+ case 7:
+ if (m_banksel & 0x40)
+ {
+ /* motherboard ram selected */
+ data = m_mb_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ switch (bitswap<8>(m_banksel, 2, 6, 5, 0, 1, 7, 3, 4) & 0x07)
+ {
+ case 2:
+ data = m_rom[1]->read(offset);
+ break;
+ case 4:
+ data = m_rom[3]->read(offset);
+ break;
+ case 0:
+ data = m_rom[5]->read(offset);
+ break;
+ case 6:
+ data = m_rom[7]->read(offset);
+ break;
+ case 7:
+ data = m_rom[8]->read(offset | 0x4000);
+ break;
+ case 3:
+ data = m_rom[9]->read(offset | 0x4000);
+ break;
+ case 5:
+ data = m_rom[10]->read(offset | 0x4000);
+ break;
+ case 1:
+ data = m_rom[11]->read(offset | 0x4000);
+ break;
+ }
+ }
+ break;
+ default:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_morleyaa_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 8:
+ if (offset == 0x3f00)
+ {
+ /* bank latch at &BF00 */
+ m_banksel = data;
+ }
+ break;
+ case 4: case 5:
+ if (m_banksel & 0x20)
+ {
+ /* motherboard ram selected */
+ m_mb_rom[m_romsel & 0x0e]->write(offset | (m_romsel & 0x01) << 14, data);
+ }
+ break;
+ case 6: case 7:
+ if (m_banksel & 0x40)
+ {
+ /* motherboard ram selected */
+ m_mb_rom[m_romsel & 0x0e]->write(offset | (m_romsel & 0x01) << 14, data);
+ }
+ break;
+ default:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/morleyaa.h b/src/devices/bus/bbc/internal/morleyaa.h
new file mode 100644
index 00000000000..f2debcff982
--- /dev/null
+++ b/src/devices/bus/bbc/internal/morleyaa.h
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Morley Electronics 'AA' Master ROM Expansion Board
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_MORLEY_H
+#define MAME_BUS_BBC_INTERNAL_MORLEY_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_morleyaa_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_morleyaa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_memory_region m_aa_rom;
+ required_device_array<bbc_romslot_device, 12> m_rom;
+
+ uint8_t m_romsel;
+ uint8_t m_banksel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_MORLEYAA, bbc_morleyaa_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_MORLEY_H */
diff --git a/src/devices/bus/bbc/internal/overlay.cpp b/src/devices/bus/bbc/internal/overlay.cpp
new file mode 100644
index 00000000000..c46a280a316
--- /dev/null
+++ b/src/devices/bus/bbc/internal/overlay.cpp
@@ -0,0 +1,224 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Vine Micros Romboard '3' (Master OS Overlay Board)
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Vine_MasterOSoverlay.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "overlay.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_OVERLAY, bbc_overlay_device, "bbc_overlay", "Vine Micros Romboard '3' (Master OS Overlay)");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( overlay )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(overlay)
+ PORT_START("link_rom1")
+ PORT_CONFNAME(0x1f, 0x0a, "ROM 1")
+ PORT_CONFSETTING(0x10, "Operating System (reserved)")
+ PORT_CONFSETTING(0x09, "1770 DFS")
+ PORT_CONFSETTING(0x0a, "Viewsheet")
+ PORT_CONFSETTING(0x0b, "Edit")
+ PORT_CONFSETTING(0x0c, "BASIC")
+ PORT_CONFSETTING(0x0d, "ADFS")
+ PORT_CONFSETTING(0x0e, "View (and some GXR)")
+ PORT_CONFSETTING(0x0f, "Terminal and Operating System (reserved)")
+ PORT_START("link_rom2")
+ PORT_CONFNAME(0x1f, 0x0b, "ROM 2")
+ PORT_CONFSETTING(0x10, "Operating System (reserved)")
+ PORT_CONFSETTING(0x09, "1770 DFS")
+ PORT_CONFSETTING(0x0a, "Viewsheet")
+ PORT_CONFSETTING(0x0b, "Edit")
+ PORT_CONFSETTING(0x0c, "BASIC")
+ PORT_CONFSETTING(0x0d, "ADFS")
+ PORT_CONFSETTING(0x0e, "View (and some GXR)")
+ PORT_CONFSETTING(0x0f, "Terminal and Operating System (reserved)")
+ PORT_START("link_rom3")
+ PORT_CONFNAME(0x1f, 0x0e, "ROM 3")
+ PORT_CONFSETTING(0x10, "Operating System (reserved)")
+ PORT_CONFSETTING(0x09, "1770 DFS")
+ PORT_CONFSETTING(0x0a, "Viewsheet")
+ PORT_CONFSETTING(0x0b, "Edit")
+ PORT_CONFSETTING(0x0c, "BASIC")
+ PORT_CONFSETTING(0x0d, "ADFS")
+ PORT_CONFSETTING(0x0e, "View (and some GXR)")
+ PORT_CONFSETTING(0x0f, "Terminal and Operating System (reserved)")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_overlay_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(overlay);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_overlay_device::device_add_mconfig(machine_config &config)
+{
+ /* 3 x 16K rom sockets */
+ BBC_ROMSLOT16(config, m_rom[0], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[1], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, nullptr);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_overlay_device - constructor
+//-------------------------------------------------
+
+bbc_overlay_device::bbc_overlay_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_OVERLAY, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+ , m_link_rom(*this, "link_rom%u", 1U)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_overlay_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_overlay_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ /* overlay banks */
+ if (m_link_rom[0]->read() == m_romsel && m_rom[0]->present())
+ {
+ data = m_rom[0]->read(offset);
+ }
+ else if (m_link_rom[1]->read() == m_romsel && m_rom[1]->present())
+ {
+ data = m_rom[1]->read(offset);
+ }
+ else if (m_link_rom[2]->read() == m_romsel && m_rom[2]->present())
+ {
+ data = m_rom[2]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ case 4: case 5: case 6: case 7:
+ /* motherboard ram selected */
+ if (m_mb_rom[m_romsel & 0x0e] && m_mb_rom[m_romsel & 0x0e]->present())
+ {
+ data = m_mb_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_overlay_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ /* overlay banks */
+ if (m_link_rom[0]->read() == m_romsel && m_rom[0]->present())
+ {
+ m_rom[0]->write(offset, data);
+ }
+ else if (m_link_rom[1]->read() == m_romsel && m_rom[1]->present())
+ {
+ m_rom[1]->write(offset, data);
+ }
+ else if (m_link_rom[2]->read() == m_romsel && m_rom[2]->present())
+ {
+ m_rom[2]->write(offset, data);
+ }
+ break;
+ case 4: case 5: case 6: case 7:
+ /* motherboard ram selected */
+ if (m_mb_rom[m_romsel & 0x0e])
+ {
+ m_mb_rom[m_romsel & 0x0e]->write(offset | (m_romsel & 0x01) << 14, data);
+ }
+ break;
+ default:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
+
+
+uint8_t bbc_overlay_device::mos_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_link_rom[0]->read() == 0x10 && m_rom[0]->present())
+ {
+ data = m_rom[0]->read(offset);
+ }
+ else if (m_link_rom[1]->read() == 0x10 && m_rom[1]->present())
+ {
+ data = m_rom[1]->read(offset);
+ }
+ else if (m_link_rom[2]->read() == 0x10 && m_rom[2]->present())
+ {
+ data = m_rom[2]->read(offset);
+ }
+ else
+ {
+ data = m_region_mos->base()[offset];
+ }
+
+ return data;
+}
diff --git a/src/devices/bus/bbc/internal/overlay.h b/src/devices/bus/bbc/internal/overlay.h
new file mode 100644
index 00000000000..3800687f5ac
--- /dev/null
+++ b/src/devices/bus/bbc/internal/overlay.h
@@ -0,0 +1,57 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Vine Micros Romboard '3' (Master OS Overlay Board)
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Vine_MasterOSoverlay.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_OVERLAY_H
+#define MAME_BUS_BBC_INTERNAL_OVERLAY_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_overlay_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_overlay_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual bool overrides_mos() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t mos_r(offs_t offset) override;
+
+private:
+ required_device_array<bbc_romslot_device, 3> m_rom;
+ required_ioport_array<3> m_link_rom;
+
+ uint8_t m_romsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_OVERLAY, bbc_overlay_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_OVERLAY_H */
diff --git a/src/devices/bus/bbc/internal/peartree.cpp b/src/devices/bus/bbc/internal/peartree.cpp
new file mode 100644
index 00000000000..49281731097
--- /dev/null
+++ b/src/devices/bus/bbc/internal/peartree.cpp
@@ -0,0 +1,295 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Peartree MRxx00 ROM/RAM Boards
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Peartree_ROMExpansion.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "peartree.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_MR3000, bbc_mr3000_device, "bbc_mr3000", "Peartree MR3000 ROM Board");
+DEFINE_DEVICE_TYPE(BBC_MR4200, bbc_mr4200_device, "bbc_mr4200", "Peartree MR4200 RAM Board");
+DEFINE_DEVICE_TYPE(BBC_MR4300, bbc_mr4300_device, "bbc_mr4300", "Peartree MR4300 ROM/RAM Board");
+DEFINE_DEVICE_TYPE(BBC_MR4800, bbc_mr4800_device, "bbc_mr4800", "Peartree MR4800 RAM Board");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( peartree )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(peartree)
+ PORT_START("wp")
+ PORT_CONFNAME(0x01, 0x00, "Write Protect Sideways RAM")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_mr4200_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(peartree);
+}
+
+ioport_constructor bbc_mr4300_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(peartree);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_mr3000_device::device_add_mconfig(machine_config &config)
+{
+ /* 4 rom sockets */
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, nullptr);
+}
+
+void bbc_mr4200_device::device_add_mconfig(machine_config &config)
+{
+ /* 32K static ram */
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+void bbc_mr4300_device::device_add_mconfig(machine_config &config)
+{
+ /* 3 rom sockets, 32K static ram */
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+void bbc_mr4800_device::device_add_mconfig(machine_config &config)
+{
+ /* 128K static ram (battery backed) */
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "nvram").set_fixed_ram(true);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_mr3000_device - constructor
+//-------------------------------------------------
+
+bbc_mr3000_device::bbc_mr3000_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+bbc_mr3000_device::bbc_mr3000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_mr3000_device(mconfig, BBC_MR3000, tag, owner, clock)
+{
+}
+
+bbc_mr4200_device::bbc_mr4200_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_mr3000_device(mconfig, BBC_MR4200, tag, owner, clock)
+ , m_wp(*this, "wp")
+{
+}
+
+//-------------------------------------------------
+// bbc_mr4300_device - constructor
+//-------------------------------------------------
+
+bbc_mr4300_device::bbc_mr4300_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+ , m_wp(*this, "wp")
+{
+}
+
+bbc_mr4300_device::bbc_mr4300_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_mr4300_device(mconfig, BBC_MR4300, tag, owner, clock)
+{
+}
+
+bbc_mr4800_device::bbc_mr4800_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_mr4300_device(mconfig, BBC_MR4800, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_mr3000_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+void bbc_mr4300_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_mr3000_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 8: case 9: case 10: case 11:
+ /* motherboard rom sockets 0-3 are re-assigned to 8-11 */
+ if (m_mb_rom[m_romsel & 0x03] && m_mb_rom[m_romsel & 0x03]->present())
+ {
+ data = m_mb_rom[m_romsel & 0x03]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14) - 0x20000];
+ }
+ break;
+ case 12: case 13: case 14: case 15:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_mr3000_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 8: case 9: case 10: case 11:
+ /* motherboard rom sockets 0-3 are re-assigned to 8-11 */
+ if (m_mb_rom[m_romsel & 0x03])
+ {
+ m_mb_rom[m_romsel & 0x03]->write(offset, data);
+ }
+ break;
+ case 12: case 13: case 14: case 15:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
+
+
+void bbc_mr4200_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 8: case 9: case 10: case 11:
+ /* motherboard rom sockets 0-3 are re-assigned to 8-11 */
+ if (m_mb_rom[m_romsel & 0x03])
+ {
+ m_mb_rom[m_romsel & 0x03]->write(offset, data);
+ }
+ break;
+ case 12: case 13: case 14: case 15:
+ /* expansion board sockets (if not write protected) */
+ if (m_rom[m_romsel] && !m_wp->read())
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
+
+
+uint8_t bbc_mr4300_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 4: case 5: case 6: case 7:
+ /* motherboard rom sockets 0-3 are re-assigned to 4-7 */
+ if (m_mb_rom[m_romsel & 0x03] && m_mb_rom[m_romsel & 0x03]->present())
+ {
+ data = m_mb_rom[m_romsel & 0x03]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14) - 0x10000];
+ }
+ break;
+ case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_mr4300_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 4: case 5: case 6: case 7:
+ /* motherboard rom sockets 0-3 are re-assigned to 4-7 */
+ if (m_mb_rom[m_romsel & 0x03])
+ {
+ m_mb_rom[m_romsel & 0x03]->write(offset, data);
+ }
+ break;
+ case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ /* expansion board sockets (if not write protected) */
+ if (m_rom[m_romsel] && !m_wp->read())
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/peartree.h b/src/devices/bus/bbc/internal/peartree.h
new file mode 100644
index 00000000000..9f9ed683396
--- /dev/null
+++ b/src/devices/bus/bbc/internal/peartree.h
@@ -0,0 +1,116 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Peartree MRxx00 ROM/RAM Boards
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Peartree_ROMExpansion.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_PEARTREE_H
+#define MAME_BUS_BBC_INTERNAL_PEARTREE_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_mr3000_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_mr3000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_mr3000_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+ uint8_t m_romsel;
+};
+
+
+class bbc_mr4200_device : public bbc_mr3000_device
+{
+public:
+ // construction/destruction
+ bbc_mr4200_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ required_ioport m_wp;
+
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+};
+
+
+class bbc_mr4300_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_mr4300_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_mr4300_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+ required_ioport m_wp;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+ uint8_t m_romsel;
+};
+
+
+class bbc_mr4800_device : public bbc_mr4300_device
+{
+public:
+ // construction/destruction
+ bbc_mr4800_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_MR3000, bbc_mr3000_device);
+DECLARE_DEVICE_TYPE(BBC_MR4200, bbc_mr4200_device);
+DECLARE_DEVICE_TYPE(BBC_MR4300, bbc_mr4300_device);
+DECLARE_DEVICE_TYPE(BBC_MR4800, bbc_mr4800_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_PEARTREE_H */
diff --git a/src/devices/bus/bbc/internal/ramamp.cpp b/src/devices/bus/bbc/internal/ramamp.cpp
new file mode 100644
index 00000000000..586159377aa
--- /dev/null
+++ b/src/devices/bus/bbc/internal/ramamp.cpp
@@ -0,0 +1,155 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Ramamp Computers Sideways RAM/ROM Board
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/RAMAMP_SidewaysRAMROM.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "ramamp.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_RAMAMP, bbc_ramamp_device, "bbc_ramamp", "Ramamp Sideways RAM/ROM Board");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( ramamp )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(ramamp)
+ PORT_START("wp")
+ PORT_CONFNAME(0x01, 0x00, "Write Protect Sideways RAM")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_ramamp_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(ramamp);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_ramamp_device::device_add_mconfig(machine_config &config)
+{
+ /* 6 rom sockets, 32K dynamic ram */
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, nullptr);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_ramamp_device - constructor
+//-------------------------------------------------
+
+bbc_ramamp_device::bbc_ramamp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_RAMAMP, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+ , m_wp(*this, "wp")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_ramamp_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x2c000, m_region_swr->base(), 0x8000);
+ memmove(m_region_swr->base() + 0x38000, m_region_swr->base() + 0x8000, 0x8000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_ramamp_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_ramamp_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ case 10: case 13:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && !m_wp->read())
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/ramamp.h b/src/devices/bus/bbc/internal/ramamp.h
new file mode 100644
index 00000000000..d8f9b62408b
--- /dev/null
+++ b/src/devices/bus/bbc/internal/ramamp.h
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Ramamp Computers Sideways RAM/ROM Board
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/RAMAMP_SidewaysRAMROM.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_RAMAMP_H
+#define MAME_BUS_BBC_INTERNAL_RAMAMP_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_ramamp_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_ramamp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+ required_ioport m_wp;
+
+ uint8_t m_romsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_RAMAMP, bbc_ramamp_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_RAMAMP_H */
diff --git a/src/devices/bus/bbc/internal/raven20.cpp b/src/devices/bus/bbc/internal/raven20.cpp
new file mode 100644
index 00000000000..a87bf2beaef
--- /dev/null
+++ b/src/devices/bus/bbc/internal/raven20.cpp
@@ -0,0 +1,112 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Raven-20 RAM expansion board
+
+ TODO:
+ - Verify behaviour of RAVEN-20 1.00, seems buggy or incomplete emulation.
+ - FAST mode (*FRON) is not understood.
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "raven20.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_RAVEN20, bbc_raven20_device, "bbc_raven20", "Raven-20 RAM expansion")
+
+
+//-------------------------------------------------
+// ROM( raven20 )
+//-------------------------------------------------
+
+ROM_START(raven20)
+ ROM_REGION(0x2000, "exp_rom", 0)
+ ROM_SYSTEM_BIOS(0, "106", "Raven-20 1.06")
+ ROMX_LOAD("raven20_1.06.rom", 0x0000, 0x2000, CRC(7efb0ab3) SHA1(e4f2acc07969e10c082355c82d8d1cbc1c08ee2e), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "100", "Raven-20 1.00")
+ ROMX_LOAD("raven20_1.00.rom", 0x0000, 0x2000, CRC(e8c8f9d5) SHA1(0f5b2a5bee23808b34eab2f027f7c1e77395c782), ROM_BIOS(1))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_raven20_device::device_rom_region() const
+{
+ return ROM_NAME( raven20 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_raven20_device - constructor
+//-------------------------------------------------
+
+bbc_raven20_device::bbc_raven20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_RAVEN20, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_raven20_device::device_start()
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ program.install_write_handler(0xd000, 0xd000, write8sm_delegate(*this, FUNC(bbc_raven20_device::enable_w)));
+ program.install_write_handler(0xc000, 0xc000, write8sm_delegate(*this, FUNC(bbc_raven20_device::disable_w)));
+
+ m_shadow = false;
+ m_ram = std::make_unique<uint8_t[]>(0x5000);
+
+ /* register for save states */
+ save_item(NAME(m_shadow));
+ save_pointer(NAME(m_ram), 0x5000);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_raven20_device::enable_w(offs_t offset, uint8_t data)
+{
+ m_shadow = true;
+}
+
+void bbc_raven20_device::disable_w(offs_t offset, uint8_t data)
+{
+ m_shadow = false;
+}
+
+uint8_t bbc_raven20_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_shadow && offset >= 0x3000)
+ data = m_ram[offset - 0x3000];
+ else
+ data = m_mb_ram->pointer()[offset];
+
+ return data;
+}
+
+void bbc_raven20_device::ram_w(offs_t offset, uint8_t data)
+{
+ if (m_shadow && offset >= 0x3000)
+ m_ram[offset - 0x3000] = data;
+ else
+ m_mb_ram->pointer()[offset] = data;
+}
diff --git a/src/devices/bus/bbc/internal/raven20.h b/src/devices/bus/bbc/internal/raven20.h
new file mode 100644
index 00000000000..0e04137afa6
--- /dev/null
+++ b/src/devices/bus/bbc/internal/raven20.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Raven-20 RAM expansion board
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_RAVEN20_H
+#define MAME_BUS_BBC_INTERNAL_RAVEN20_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_raven20_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_raven20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual bool overrides_ram() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+
+private:
+ void enable_w(offs_t offset, uint8_t data);
+ void disable_w(offs_t offset, uint8_t data);
+
+ bool m_shadow;
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_RAVEN20, bbc_raven20_device)
+
+
+#endif // MAME_BUS_BBC_INTERNAL_RAVEN20_H
diff --git a/src/devices/bus/bbc/internal/romex.cpp b/src/devices/bus/bbc/internal/romex.cpp
new file mode 100644
index 00000000000..9d7932db81f
--- /dev/null
+++ b/src/devices/bus/bbc/internal/romex.cpp
@@ -0,0 +1,134 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ GCC (Cambridge) Romex 13
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/GCC_Romex13.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "romex.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_ROMEX13, bbc_romex13_device, "bbc_romex13", "GCC Romex13 ROM Expansion");
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_romex13_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot2 is unavailable when board is fitted, replaced by socket on board */
+ //config.device_remove(":romslot2");
+
+ /* 13 rom sockets */
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, nullptr);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_romex13_device - constructor
+//-------------------------------------------------
+
+bbc_romex13_device::bbc_romex13_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_ROMEX13, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_romex13_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x30000, m_region_swr->base(), 0x10000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_romex13_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_romex13_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/romex.h b/src/devices/bus/bbc/internal/romex.h
new file mode 100644
index 00000000000..b9542937ebf
--- /dev/null
+++ b/src/devices/bus/bbc/internal/romex.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ GCC (Cambridge) Romex 13
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/GCC_Romex13.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_ROMEX_H
+#define MAME_BUS_BBC_INTERNAL_ROMEX_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_romex13_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_romex13_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ uint8_t m_romsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_ROMEX13, bbc_romex13_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_ROMEX_H */
diff --git a/src/devices/bus/bbc/internal/stl2m128.cpp b/src/devices/bus/bbc/internal/stl2m128.cpp
new file mode 100644
index 00000000000..46b595aedfa
--- /dev/null
+++ b/src/devices/bus/bbc/internal/stl2m128.cpp
@@ -0,0 +1,248 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk Twomeg 128K Shadow and Sideways ROM/RAM board
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "stl2m128.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_STL2M128, bbc_stl2m128_device, "bbc_stl2m128", "Solidisk Twomeg 128K RAM/ROM Expansion");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( stl2m128 )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(stl2m128)
+ PORT_START("wp")
+ PORT_CONFNAME(0x01, 0x00, "Write Protect Sideways RAM")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_stl2m128_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(stl2m128);
+}
+
+//-------------------------------------------------
+// ROM( stl2m128 )
+//-------------------------------------------------
+
+ROM_START(stl2m128)
+ ROM_REGION(0x4000, "rom", ROMREGION_ERASEFF)
+ // ROM image usually distributed on floppy, to load into RAM
+ ROM_LOAD("manger128-1.00.rom", 0x0000, 0x102a, CRC(dbe84acb) SHA1(d170632b88d0ab276a919b0076dca305094a39b2))
+ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_stl2m128_device::device_add_mconfig(machine_config &config)
+{
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_stl2m128_device::device_rom_region() const
+{
+ return ROM_NAME(stl2m128);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_stl2m128_device - constructor
+//-------------------------------------------------
+
+bbc_stl2m128_device::bbc_stl2m128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_STL2M128, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+ , m_wp(*this, "wp")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_stl2m128_device::device_start()
+{
+ m_ram = std::make_unique<uint8_t[]>(0x20000);
+
+ /* copy rom image into ram bank c */
+ memcpy(&m_ram[0x10000], memregion("rom")->base(), 0x4000);
+
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x20000, m_region_swr->base(), 0x10000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_pointer(NAME(m_ram), 0x20000);
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_shadow));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_stl2m128_device::romsel_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0x0c)
+ {
+ case 0x00:
+ m_romsel = data & 0x0f;
+ break;
+ case 0x04:
+ m_shadow = data;
+ break;
+ }
+}
+
+uint8_t bbc_stl2m128_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (BIT(m_shadow, 7) && offset >= 0x2000)
+ {
+ if (BIT(m_shadow, 1))
+ {
+ /* banks E/F */
+ data = m_ram[offset | 0x18000];
+ }
+ else
+ {
+ /* banks C/D */
+ data = m_ram[offset | 0x10000];
+ }
+ }
+ else
+ {
+ data = m_mb_ram->pointer()[offset];
+ }
+
+ return data;
+}
+
+void bbc_stl2m128_device::ram_w(offs_t offset, uint8_t data)
+{
+ if (BIT(m_shadow, 7) && offset >= 0x2000)
+ {
+ if (BIT(m_shadow, 1))
+ {
+ /* banks E/F */
+ m_ram[offset | 0x18000] = data;
+ }
+ else
+ {
+ /* banks C/D */
+ m_ram[offset | 0x10000] = data;
+ }
+ }
+ else
+ {
+ m_mb_ram->pointer()[offset] = data;
+ }
+}
+
+uint8_t bbc_stl2m128_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ case 8: case 9: case 10: case 11:
+ /* expansion board rom sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 12: case 13: case 14: case 15:
+ /* expansion board ram sockets */
+ data = m_ram[offset | ((m_romsel & 0x03) << 14) | ((m_romsel & 0x08) << 13)];
+ break;
+ }
+
+
+ return data;
+}
+
+void bbc_stl2m128_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ case 8: case 9: case 10: case 11:
+ /* expansion board rom sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 12: case 13: case 14: case 15:
+ /* expansion board ram sockets */
+ if (!m_wp->read())
+ {
+ m_ram[offset | ((m_romsel & 0x03) << 14) | ((m_romsel & 0x08) << 13)] = data;
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/stl2m128.h b/src/devices/bus/bbc/internal/stl2m128.h
new file mode 100644
index 00000000000..2c5f327ab19
--- /dev/null
+++ b/src/devices/bus/bbc/internal/stl2m128.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk Twomeg 128K Shadow and Sideways ROM/RAM board
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_STL2M128_H
+#define MAME_BUS_BBC_INTERNAL_STL2M128_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_stl2m128_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_stl2m128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual bool overrides_ram() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+ virtual void romsel_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+ required_ioport m_wp;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+
+ uint8_t m_romsel;
+ uint8_t m_shadow;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_STL2M128, bbc_stl2m128_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_STL2M128_H */
diff --git a/src/devices/bus/bbc/internal/stl4m32.cpp b/src/devices/bus/bbc/internal/stl4m32.cpp
new file mode 100644
index 00000000000..bd5e3e0d40e
--- /dev/null
+++ b/src/devices/bus/bbc/internal/stl4m32.cpp
@@ -0,0 +1,303 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk Fourmeg RAM/ROM Expansions
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Solidisk_4Meg.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "stl4m32.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_STL4M32, bbc_stl4m32_device, "bbc_stl4m32", "Solidisk Fourmeg 32K RAM/ROM Expansion");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( stl4m )
+//-------------------------------------------------
+
+INPUT_PORTS_START(stl4m32)
+ PORT_START("stl4m_clock")
+ PORT_CONFNAME(0x01, 0x01, "4MHz Clock") PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_stl4m32_device, clock_switch, 0)
+ PORT_CONFSETTING(0x00, "2MHz")
+ PORT_CONFSETTING(0x01, "4MHz")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_stl4m32_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(stl4m32);
+}
+
+
+//-------------------------------------------------
+// ROM( stl4m32 )
+//-------------------------------------------------
+
+ROM_START(stl4m32)
+ ROM_REGION(0x4000, "rom", 0)
+ ROM_SYSTEM_BIOS(0, "30", "Manager 3.00 (16.6.86)")
+ ROMX_LOAD("manager_4meg32k-16.6.86.rom", 0x0000, 0x4000, CRC(2024cd0d) SHA1(cf45217ac88480a6963cbf75e8cf684cd81c7b09), ROM_BIOS(0))
+ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_stl4m32_device::device_add_mconfig(machine_config &config)
+{
+ //M65SC02(config.replace(), m_maincpu, DERIVED_CLOCK(1, 4));
+
+ /* 5 x 32K rom sockets */
+ BBC_ROMSLOT32(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+
+const tiny_rom_entry *bbc_stl4m32_device::device_rom_region() const
+{
+ return ROM_NAME(stl4m32);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_stl4m32_device - constructor
+//-------------------------------------------------
+
+bbc_stl4m32_device::bbc_stl4m32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_STL4M32, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_stl4m32_device::device_start()
+{
+ m_ram = std::make_unique<uint8_t[]>(0x8000);
+
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x30000, m_region_swr->base() + 0xc000, 0x4000);
+ memcpy(m_region_swr->base() + 0x28000, memregion("rom")->base(), 0x4000);
+ memset(m_region_swr->base() + 0x0c000, 0xff, 0x4000);
+
+ /* register for save states */
+ save_pointer(NAME(m_ram), 0x8000);
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_ramsel));
+ save_item(NAME(m_shadow));
+}
+
+
+//-------------------------------------------------
+// device_reset_after_children - reset after child devices
+//-------------------------------------------------
+
+void bbc_stl4m32_device::device_reset() //_after_children()
+{
+ /* set cpu clock to 4mhz */
+ //m_maincpu->set_clock(DERIVED_CLOCK(1, 4));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+INPUT_CHANGED_MEMBER(bbc_stl4m32_device::clock_switch)
+{
+ switch (newval)
+ {
+ case 0:
+ //m_maincpu->set_clock(DERIVED_CLOCK(1, 8));
+ break;
+ case 1:
+ //m_maincpu->set_clock(DERIVED_CLOCK(1, 4));
+ break;
+ }
+}
+
+void bbc_stl4m32_device::romsel_w(offs_t offset, uint8_t data)
+{
+ logerror("romsel_w: %04x = %02x\n", offset | 0xfe30, data);
+
+ switch (offset & 0x0e)
+ {
+ case 0x00:
+ m_romsel = data & 0x0f;
+ break;
+ case 0x02:
+ m_ramsel = data;
+ break;
+ case 0x04:
+ m_shadow = data;
+ break;
+ }
+}
+
+uint8_t bbc_stl4m32_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (BIT(m_shadow, 7) && offset >= 0x2000)
+ {
+ data = m_ram[offset];
+ }
+ else
+ {
+ data = m_mb_ram->pointer()[offset];
+ }
+
+ return data;
+}
+
+void bbc_stl4m32_device::ram_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xff) == 0x00)
+ logerror("ram_w: %04x = %02x\n", offset, data);
+
+ if (BIT(m_romsel, 7) && offset >= 0x2000)
+ {
+ m_ram[offset] = data;
+ }
+ else
+ {
+ m_mb_ram->pointer()[offset] = data;
+ }
+}
+
+
+uint8_t bbc_stl4m32_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (BIT(m_romsel, 7) && offset < 0x2000)
+ {
+ data = m_ram[offset];
+ }
+ else
+ {
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13:
+ /* expansion board rom sockets */
+ if (m_rom[m_romsel & 0x0e] && m_rom[m_romsel & 0x0e]->present())
+ {
+ data = m_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ case 14: case 15:
+ /* expansion board ram sockets */
+ data = m_ram[offset | ((m_romsel & 0x01) << 14)];
+ break;
+ }
+ }
+
+ return data;
+}
+
+void bbc_stl4m32_device::paged_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xff) == 0x00)
+ logerror("paged_w: %04x = %02x\n", offset | 0x8000, data);
+
+ if (BIT(m_romsel, 7) && offset < 0x2000)
+ {
+ m_ram[offset] = data;
+ }
+ else
+ {
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13:
+ /* expansion board rom sockets */
+ if (m_rom[m_romsel & 0x0e])
+ {
+ m_rom[m_romsel & 0x0e]->write(offset | (m_romsel & 0x01) << 14, data);
+ }
+ break;
+ }
+
+ if (m_ramsel == 14 || m_ramsel == 15)
+ {
+ /* expansion board ram sockets */
+ m_ram[offset | ((m_ramsel & 0x01) << 14)] = data;
+ }
+ }
+}
+
+
+uint8_t bbc_stl4m32_device::mos_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ //if (BIT(m_shadow, 7) && offset >= 0x2000)
+ //{
+ // data = m_ram[offset];
+ //}
+ //else
+ //{
+ data = m_region_mos->base()[offset];
+ //}
+
+ return data;
+}
+
+void bbc_stl4m32_device::mos_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xff) == 0x00)
+ logerror("mos_w: %04x = %02x\n", offset | 0xc000, data);
+
+ //if (BIT(m_romsel, 7) && offset >= 0x2000)
+ //{
+ // m_ram[offset] = data;
+ //}
+} \ No newline at end of file
diff --git a/src/devices/bus/bbc/internal/stl4m32.h b/src/devices/bus/bbc/internal/stl4m32.h
new file mode 100644
index 00000000000..ac939d6d4ff
--- /dev/null
+++ b/src/devices/bus/bbc/internal/stl4m32.h
@@ -0,0 +1,67 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk Fourmeg RAM/ROM Expansions
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Solidisk_4Meg.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_STL4M32_H
+#define MAME_BUS_BBC_INTERNAL_STL4M32_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_stl4m32_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_stl4m32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(clock_switch);
+
+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 const tiny_rom_entry *device_rom_region() const override;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual bool overrides_ram() override { return true; }
+ virtual bool overrides_mos() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+ virtual void romsel_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t mos_r(offs_t offset) override;
+ virtual void mos_w(offs_t offset, uint8_t data) override;
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+
+ uint8_t m_romsel;
+ uint8_t m_ramsel;
+ uint8_t m_shadow;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_STL4M32, bbc_stl4m32_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_STL4M32_H */
diff --git a/src/devices/bus/bbc/internal/stlswr.cpp b/src/devices/bus/bbc/internal/stlswr.cpp
new file mode 100644
index 00000000000..f4992197453
--- /dev/null
+++ b/src/devices/bus/bbc/internal/stlswr.cpp
@@ -0,0 +1,192 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk Sideways RAM
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Solidisk_128KSWE.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "stlswr.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_STLSWR16, bbc_stlswr16_device, "bbc_stlswr16", "Solidisk SWR16 - 16K Sideways RAM");
+DEFINE_DEVICE_TYPE(BBC_STLSWR32, bbc_stlswr32_device, "bbc_stlswr32", "Solidisk SWR32 - 32K Sideways RAM");
+DEFINE_DEVICE_TYPE(BBC_STLSWR64, bbc_stlswr64_device, "bbc_stlswr64", "Solidisk SWR64 - 64K Sideways RAM");
+DEFINE_DEVICE_TYPE(BBC_STLSWR128, bbc_stlswr128_device, "bbc_stlswr128", "Solidisk SWR128 - 128K Sideways RAM");
+
+
+//-------------------------------------------------
+// ROM( stlswr )
+//-------------------------------------------------
+
+ROM_START(stlswr)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_SYSTEM_BIOS(0, "13", "Toolkit 1.3 03/03/86")
+ ROMX_LOAD("toolkit-1.3-16k-128k-03-03-86.rom", 0x0000, 0x4000, CRC(a1745d10) SHA1(1821e74feca60b95766ead06df20f6db22e2b4bb), ROM_BIOS(0))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_stlswr16_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot3 is unavailable when board is fitted */
+ //config.device_remove(":romslot3");
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+void bbc_stlswr32_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot3 is unavailable when board is fitted */
+ //config.device_remove(":romslot3");
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+void bbc_stlswr64_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot3 is unavailable when board is fitted */
+ //config.device_remove(":romslot3");
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+void bbc_stlswr128_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot3 is unavailable when board is fitted */
+ //config.device_remove(":romslot3");
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_stlswr_device::device_rom_region() const
+{
+ return ROM_NAME(stlswr);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_stlswr_device - constructor
+//-------------------------------------------------
+
+bbc_stlswr_device::bbc_stlswr_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+bbc_stlswr16_device::bbc_stlswr16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_stlswr_device(mconfig, BBC_STLSWR16, tag, owner, clock)
+{
+}
+
+bbc_stlswr32_device::bbc_stlswr32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_stlswr_device(mconfig, BBC_STLSWR32, tag, owner, clock)
+{
+}
+
+bbc_stlswr64_device::bbc_stlswr64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_stlswr_device(mconfig, BBC_STLSWR64, tag, owner, clock)
+{
+}
+
+bbc_stlswr128_device::bbc_stlswr128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_stlswr_device(mconfig, BBC_STLSWR128, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_stlswr_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_ramsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_stlswr_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_stlswr_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+
+ /* expansion board sockets */
+ if (m_rom[m_ramsel])
+ {
+ m_rom[m_ramsel]->write(offset, data);
+ }
+}
diff --git a/src/devices/bus/bbc/internal/stlswr.h b/src/devices/bus/bbc/internal/stlswr.h
new file mode 100644
index 00000000000..db7e263ce28
--- /dev/null
+++ b/src/devices/bus/bbc/internal/stlswr.h
@@ -0,0 +1,108 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk Sideways RAM
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Solidisk_128KSWE.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_STLSWR_H
+#define MAME_BUS_BBC_INTERNAL_STLSWR_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_stlswr_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_stlswr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_stlswr_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+ virtual void latch_fe60_w(uint8_t data) override { m_ramsel = (data & 0x07) | 0x08; }
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ uint8_t m_romsel;
+ uint8_t m_ramsel;
+};
+
+
+class bbc_stlswr16_device : public bbc_stlswr_device
+{
+public:
+ // construction/destruction
+ bbc_stlswr16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+
+class bbc_stlswr32_device : public bbc_stlswr_device
+{
+public:
+ // construction/destruction
+ bbc_stlswr32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+
+class bbc_stlswr64_device : public bbc_stlswr_device
+{
+public:
+ // construction/destruction
+ bbc_stlswr64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+
+class bbc_stlswr128_device : public bbc_stlswr_device
+{
+public:
+ // construction/destruction
+ bbc_stlswr128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_STLSWR16, bbc_stlswr16_device);
+DECLARE_DEVICE_TYPE(BBC_STLSWR32, bbc_stlswr32_device);
+DECLARE_DEVICE_TYPE(BBC_STLSWR64, bbc_stlswr64_device);
+DECLARE_DEVICE_TYPE(BBC_STLSWR128, bbc_stlswr128_device);
+
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_STLSWR_H */
diff --git a/src/devices/bus/bbc/internal/we32kram.cpp b/src/devices/bus/bbc/internal/we32kram.cpp
new file mode 100644
index 00000000000..ec21a7efb9d
--- /dev/null
+++ b/src/devices/bus/bbc/internal/we32kram.cpp
@@ -0,0 +1,142 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics 32K RAM card
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_32KRAMcard.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "we32kram.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_WE32KRAM, bbc_we32kram_device, "bbc_we32kram", "Watford Electronics 32K Shadow RAM");
+
+
+//-------------------------------------------------
+// ROM( we32kram )
+//-------------------------------------------------
+
+ROM_START(we32kram)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_SYSTEM_BIOS(0, "240", "v2.40")
+ ROMX_LOAD("we32kram_v2.40.rom", 0x0000, 0x2000, CRC(db9c3a1a) SHA1(0a5efb084eb1ae353b9c79c026e9e26cd7695293), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "200", "v2.00")
+ ROMX_LOAD("we32kram_v2.00.rom", 0x0000, 0x2000, CRC(1eff9b23) SHA1(98a3084b20c92427c2e9def58ade96f42659e20a), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "100", "v1.00")
+ ROMX_LOAD("we32kram_v1.00.rom", 0x0000, 0x2000, CRC(7962b5db) SHA1(1b59a3354cfc704ad8aa60b0ed16e4cd2d815031), ROM_BIOS(2))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_we32kram_device::device_rom_region() const
+{
+ return ROM_NAME(we32kram);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_we32kram_device - constructor
+//-------------------------------------------------
+
+bbc_we32kram_device::bbc_we32kram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_WE32KRAM, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_we32kram_device::device_start()
+{
+ m_shadow = 2;
+ m_ram = std::make_unique<uint8_t[]>(0x8000);
+
+ /* register for save states */
+ save_item(NAME(m_shadow));
+ save_pointer(NAME(m_ram), 0x8000);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bbc_we32kram_device::device_reset()
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ program.install_write_handler(0xfffc, 0xffff, write8sm_delegate(*this, FUNC(bbc_we32kram_device::control_w)));
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_we32kram_device::control_w(offs_t offset, uint8_t data)
+{
+ m_shadow = offset;
+}
+
+uint8_t bbc_we32kram_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_shadow)
+ {
+ case 0:
+ /* &fffc - swap whole memory */
+ data = m_ram[offset];
+ break;
+ case 2:
+ /* &fffe - select BBC ram */
+ data = m_mb_ram->pointer()[offset];
+ break;
+ case 3:
+ /* &ffff - select Watford ram */
+ if (offset >= 0x3000)
+ data = m_ram[offset];
+ else
+ data = m_mb_ram->pointer()[offset];
+ break;
+ }
+
+ return data;
+}
+
+void bbc_we32kram_device::ram_w(offs_t offset, uint8_t data)
+{
+ switch (m_shadow)
+ {
+ case 0:
+ /* &fffc - swap whole memory */
+ m_ram[offset] = data;
+ break;
+ case 2:
+ /* &fffe - select BBC ram */
+ m_mb_ram->pointer()[offset] = data;
+ break;
+ case 3:
+ /* &ffff - select Watford ram */
+ if (offset >= 0x3000)
+ m_ram[offset] = data;
+ else
+ m_mb_ram->pointer()[offset] = data;
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/we32kram.h b/src/devices/bus/bbc/internal/we32kram.h
new file mode 100644
index 00000000000..aa10005292b
--- /dev/null
+++ b/src/devices/bus/bbc/internal/we32kram.h
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics 32K RAM card
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_32KRAMcard.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_WE32KRAM_H
+#define MAME_BUS_BBC_INTERNAL_WE32KRAM_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_we32kram_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_we32kram_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 bool overrides_ram() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+
+private:
+ void control_w(offs_t offset, uint8_t data);
+
+ uint8_t m_shadow;
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_WE32KRAM, bbc_we32kram_device);
+
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_WE32KRAM_H */
diff --git a/src/devices/bus/bbc/internal/werom.cpp b/src/devices/bus/bbc/internal/werom.cpp
new file mode 100644
index 00000000000..bc38500dee8
--- /dev/null
+++ b/src/devices/bus/bbc/internal/werom.cpp
@@ -0,0 +1,260 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics 12 ROM Board
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_12ROMboard.html
+
+ Watford Electronics 13 ROM Board
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_13ROMBoard.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "werom.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_WE12ROM, bbc_we12rom_device, "bbc_we12rom", "Watford Electronics 12 ROM Board");
+DEFINE_DEVICE_TYPE(BBC_WE13ROM, bbc_we13rom_device, "bbc_we13rom", "Watford Electronics 13 ROM Board");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( werom )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(werom)
+ PORT_START("wp")
+ PORT_CONFNAME(0x01, 0x00, "Write Protect Sideways RAM")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_we12rom_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(werom);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_we12rom_device::device_add_mconfig(machine_config &config)
+{
+ /* 12 rom sockets, 16K static ram (battery backed) */
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, nullptr);
+}
+
+void bbc_we13rom_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot2 is unavailable when board is fitted, replaced by socket on board */
+ //config.device_remove(":romslot2");
+
+ /* 13 rom sockets, 16K static ram (battery backed) */
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "nvram").set_fixed_ram(true);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_werom_device - constructor
+//-------------------------------------------------
+
+bbc_werom_device::bbc_werom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+bbc_we12rom_device::bbc_we12rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_werom_device(mconfig, BBC_WE12ROM, tag, owner, clock)
+ , m_wp(*this, "wp")
+{
+}
+
+bbc_we13rom_device::bbc_we13rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_werom_device(mconfig, BBC_WE13ROM, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_we12rom_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x2c000, m_region_swr->base(), 0xc000);
+ memmove(m_region_swr->base() + 0x3c000, m_region_swr->base() + 0xc000, 0x4000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+void bbc_we13rom_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x2c000, m_region_swr->base(), 0x10000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_we12rom_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_we12rom_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ /* sideways ram (if not write protected) */
+ if (!m_wp->read())
+ {
+ m_rom[14]->write(offset, data);
+ }
+ break;
+ }
+}
+
+
+uint8_t bbc_we13rom_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_we13rom_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ /* sideways ram */
+ m_rom[15]->write(offset, data);
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/werom.h b/src/devices/bus/bbc/internal/werom.h
new file mode 100644
index 00000000000..4e95ba120d8
--- /dev/null
+++ b/src/devices/bus/bbc/internal/werom.h
@@ -0,0 +1,90 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics 12 ROM Board
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_12ROMboard.html
+
+ Watford Electronics 13 ROM Board
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_13ROMBoard.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_WEROM_H
+#define MAME_BUS_BBC_INTERNAL_WEROM_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_werom_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_werom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_werom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+
+ uint8_t m_romsel;
+};
+
+
+class bbc_we12rom_device : public bbc_werom_device
+{
+public:
+ // construction/destruction
+ bbc_we12rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_ioport m_wp;
+};
+
+
+class bbc_we13rom_device : public bbc_werom_device
+{
+public:
+ // construction/destruction
+ bbc_we13rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_WE12ROM, bbc_we12rom_device);
+DECLARE_DEVICE_TYPE(BBC_WE13ROM, bbc_we13rom_device);
+
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_WEROM_H */
diff --git a/src/devices/bus/bbc/internal/weromram.cpp b/src/devices/bus/bbc/internal/weromram.cpp
new file mode 100644
index 00000000000..ceb8be3e270
--- /dev/null
+++ b/src/devices/bus/bbc/internal/weromram.cpp
@@ -0,0 +1,133 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics ROM/RAM Board
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_RAMROMBoard.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "weromram.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_WEROMRAM, bbc_weromram_device, "bbc_weromram", "Watford Electronics ROM/RAM Board");
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_weromram_device::device_add_mconfig(machine_config &config)
+{
+ /* 3 rom sockets, 64K dynamic ram, 16K static ram (battery backed) */
+ BBC_ROMSLOT16(config, m_rom[0], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[1], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[3], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, nullptr);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_weromram_device - constructor
+//-------------------------------------------------
+
+bbc_weromram_device::bbc_weromram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_WEROMRAM, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_weromram_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x2c000, m_region_swr->base(), 0xc000);
+ memmove(m_region_swr->base() + 0x3c000, m_region_swr->base() + 0xc000, 0x4000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_ramsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_weromram_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 8: case 9: case 10: case 11:
+ /* motherboard rom sockets 0-3 are re-assigned to 8-11 */
+ if (m_mb_rom[m_romsel & 0x03] && m_mb_rom[m_romsel & 0x03]->present())
+ {
+ data = m_mb_rom[m_romsel & 0x03]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14) - 0x20000];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_weromram_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 8: case 9: case 10: case 11:
+ /* motherboard rom sockets 0-3 are re-assigned to 8-11 */
+ if (m_mb_rom[m_romsel & 0x03])
+ {
+ m_mb_rom[m_romsel & 0x03]->write(offset, data);
+ }
+ break;
+ }
+
+ /* expansion board sockets */
+ if (m_rom[m_ramsel])
+ {
+ m_rom[m_ramsel]->write(offset, data);
+ }
+}
diff --git a/src/devices/bus/bbc/internal/weromram.h b/src/devices/bus/bbc/internal/weromram.h
new file mode 100644
index 00000000000..b85c9d031ab
--- /dev/null
+++ b/src/devices/bus/bbc/internal/weromram.h
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics ROM/RAM Board
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_RAMROMBoard.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_WEROMRAM_H
+#define MAME_BUS_BBC_INTERNAL_WEROMRAM_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_weromram_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_weromram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ void ramsel_w(offs_t offset, uint8_t data);
+
+ uint8_t m_romsel;
+ uint8_t m_ramsel;
+};
+
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_WEROMRAM, bbc_weromram_device);
+
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_WEROMRAM_H */