summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/mc10/mcx128.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/mc10/mcx128.cpp')
-rw-r--r--src/devices/bus/mc10/mcx128.cpp371
1 files changed, 371 insertions, 0 deletions
diff --git a/src/devices/bus/mc10/mcx128.cpp b/src/devices/bus/mc10/mcx128.cpp
new file mode 100644
index 00000000000..32c9239afb5
--- /dev/null
+++ b/src/devices/bus/mc10/mcx128.cpp
@@ -0,0 +1,371 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/***************************************************************************
+
+ mcx128.cpp
+
+ Code for emulating Darren Atkinson's MCX-128 cartridge
+
+ Features:
+ 128K of RAM expansion
+ 16K of ROM expansion
+
+ New MC-10 memory map defined by this cartridge:
+
+ 0000 - 0003 6803 Ports
+ 0004 - 0007 Expansion RAM
+ 0008 - 000E 6803 Status / Control
+ 000F Expansion RAM
+ 0010 - 0013 6803 UART
+ 0014 6803 RAM Control Reg
+ 0015 - 001F Unused
+ 0020 - 007F Expansion RAM
+ 0080 - 00FF On-chip CPU RAM / Expansion RAM
+ 0100 - 3FFF Expansion RAM
+ 4000 - 5FFF Built-In RAM / Expansion RAM
+ 6000 - BEFF Expansion RAM
+ BF00 RAM Bank Control Reg
+ BF01 ROM Map Control Reg
+ BF80 - BFFF Keyboard / VDG / Sound
+ C000 - DFFF EPROM or Expansion RAM
+ E000 - FFFF Built-in ROM, EPROM or Expansion RAM
+
+ Deficiency:
+
+ * Writing to 6803 chip RAM at $80 to $ff should be mirrored
+ to external RAM.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mcx128.h"
+
+//#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+
+ROM_START(mc10_mcx128)
+ ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00)
+ ROM_LOAD("mcx128bas.rom", 0x0000, 0x4000, CRC(11202e4b) SHA1(36c30d0f198a1bffee88ef29d92f2401447a91f4))
+ROM_END
+
+ROM_START(alice_mcx128)
+ ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00)
+ ROM_LOAD("alice128bas.rom", 0x0000, 0x4000, CRC(a737544a) SHA1(c8fd92705fc42deb6a0ffac6274e27fd61ecd4cc))
+ROM_END
+
+//**************************************************************************
+// TYPE DECLARATIONS
+//**************************************************************************
+
+// ======================> mc10_pak_device
+
+class mc10_pak_mcx128_device :
+ public device_t,
+ public device_mc10cart_interface
+{
+public:
+ // construction/destruction
+ mc10_pak_mcx128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // construction/destruction
+ mc10_pak_mcx128_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_post_load() override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME(mc10_mcx128);
+ }
+
+ u8 control_register_read(offs_t offset);
+ void control_register_write(offs_t offset, u8 data);
+
+ void write_ram_mirror(address_space &space, offs_t offset, u8 data);
+
+ void view_map0(address_map &map);
+ void view_map1(address_map &map);
+ void view_map2(address_map &map);
+ void view_map3(address_map &map);
+ void view_map4(address_map &map);
+ void view_map5(address_map &map);
+ void view_map6(address_map &map);
+ void view_map7(address_map &map);
+
+
+private:
+ memory_share_creator<u8> m_share;
+ memory_view m_view;
+ memory_bank_array_creator<8> m_bank;
+ uint8_t ram_bank_cr;
+ uint8_t rom_map_cr;
+
+ void update_banks();
+
+};
+
+DEFINE_DEVICE_TYPE_PRIVATE(MC10_PAK_MCX128, device_mc10cart_interface, mc10_pak_mcx128_device, "mc10_mcx128", "Darren Atkinson's MCX-128 cartridge")
+
+//-------------------------------------------------
+// mc10_pak_device - constructor
+//-------------------------------------------------
+
+mc10_pak_mcx128_device::mc10_pak_mcx128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ :mc10_pak_mcx128_device(mconfig, MC10_PAK_MCX128, tag, owner, clock)
+{
+}
+
+mc10_pak_mcx128_device::mc10_pak_mcx128_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_mc10cart_interface(mconfig, *this)
+ , m_share(*this, "ext_ram", 1024*128, ENDIANNESS_BIG)
+ , m_view(*this, "mcx_view")
+ , m_bank(*this, "bank%u", 0U)
+{
+}
+
+void mc10_pak_mcx128_device::view_map0(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0x5fff).bankr("bank3").w(FUNC(mc10_pak_mcx128_device::write_ram_mirror));
+ map(0x6000, 0xbeff).bankrw("bank4");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xfeff).rom().region("eprom",0x0000).bankw("bank5");
+ map(0xff00, 0xffff).rom().region("eprom",0x3f00).bankw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map1(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0x5fff).bankr("bank3").w(FUNC(mc10_pak_mcx128_device::write_ram_mirror));
+ map(0x6000, 0xbeff).bankrw("bank4");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xdfff).bankrw("bank5");
+ map(0xe000, 0xfeff).rom().region("eprom",0x2000).bankw("bank6");
+ map(0xff00, 0xffff).rom().region("eprom",0x3f00).bankw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map2(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0x5fff).bankr("bank3").w(FUNC(mc10_pak_mcx128_device::write_ram_mirror));
+ map(0x6000, 0xbeff).bankrw("bank4");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xdfff).bankrw("bank5");
+ map(0xe000, 0xfeff).bankw("bank6");
+ map(0xff00, 0xffff).bankw("bank7");
+// 0xe000, 0xffff: read internal ROM
+}
+
+void mc10_pak_mcx128_device::view_map3(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0x5fff).bankr("bank3").w(FUNC(mc10_pak_mcx128_device::write_ram_mirror));
+ map(0x6000, 0xbeff).bankrw("bank4");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xfeff).bankrw("bank5");
+ map(0xff00, 0xffff).bankrw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map4(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0xbeff).bankrw("bank3");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xfeff).rom().region("eprom",0x0000).bankw("bank5");
+ map(0xff00, 0xffff).rom().region("eprom",0x3f00).bankw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map5(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0xbeff).bankrw("bank3");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xdfff).bankrw("bank5");
+ map(0xe000, 0xfeff).rom().region("eprom",0x2000).bankw("bank6");
+ map(0xff00, 0xffff).rom().region("eprom",0x3f00).bankw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map6(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0xbeff).bankrw("bank3");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xdfff).bankrw("bank5");
+ map(0xe000, 0xfeff).bankw("bank6");
+ map(0xff00, 0xffff).bankw("bank7");
+// 0xe000, 0xffff: read internal ROM
+}
+
+void mc10_pak_mcx128_device::view_map7(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0xbeff).bankrw("bank3");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xfeff).bankrw("bank5");
+ map(0xff00, 0xffff).bankrw("bank7");
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mc10_pak_mcx128_device::device_start()
+{
+ save_item(NAME(ram_bank_cr));
+ save_item(NAME(rom_map_cr));
+
+ // 0x0004 - 0x0007
+ m_bank[0]->configure_entry(0, &m_share[0x00004]);
+ m_bank[0]->configure_entry(1, &m_share[0x10004]);
+
+ // 0x000f - 0x000f
+ m_bank[1]->configure_entry(0, &m_share[0x0000f]);
+ m_bank[1]->configure_entry(1, &m_share[0x1000f]);
+
+ // 0x0000 - 0x3fff
+ m_bank[2]->configure_entry(0, &m_share[0x00020]);
+ m_bank[2]->configure_entry(1, &m_share[0x10020]);
+
+ // 0x4000 - 0x5fff
+ m_bank[3]->configure_entry(0, &m_share[0x08000]);
+ m_bank[3]->configure_entry(1, &m_share[0x18000]);
+
+ // 0x6000 - 0xbeff
+ m_bank[4]->configure_entry(0, &m_share[0x0a000]);
+ m_bank[4]->configure_entry(1, &m_share[0x1a000]);
+
+ // 0xc000 - 0xdfff
+ m_bank[5]->configure_entry(0, &m_share[0x04000]);
+ m_bank[5]->configure_entry(1, &m_share[0x14000]);
+
+ // 0xe000 - 0xffff
+ m_bank[6]->configure_entry(0, &m_share[0x06000]);
+ m_bank[6]->configure_entry(1, &m_share[0x16000]);
+
+ // 0xff00 - 0xffff
+ m_bank[7]->configure_entry(0, &m_share[0x07f00]);
+ m_bank[7]->configure_entry(1, &m_share[0x07f00]);
+
+ owning_slot().memspace().install_view(0x0000, 0xffff, m_view);
+
+ m_view[0].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map0);
+ m_view[1].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map1);
+ m_view[2].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map2);
+ m_view[3].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map3);
+ m_view[4].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map4);
+ m_view[5].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map5);
+ m_view[6].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map6);
+ m_view[7].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map7);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific startup
+//-------------------------------------------------
+
+void mc10_pak_mcx128_device::device_reset()
+{
+ ram_bank_cr = 0;
+ rom_map_cr = 0;
+ update_banks();
+}
+
+void mc10_pak_mcx128_device::device_post_load()
+{
+ update_banks();
+}
+
+void mc10_pak_mcx128_device::write_ram_mirror(address_space &space, offs_t offset, u8 data)
+{
+ std::optional<int> cur_slot = m_view.entry();
+ m_share[0x08000+offset] = data;
+
+ if (cur_slot.has_value())
+ {
+ int cur_slot_int = *cur_slot;
+ m_view.disable();
+ space.write_byte(0x4000+offset, data);
+ m_view.select(cur_slot_int);
+ }
+}
+
+u8 mc10_pak_mcx128_device::control_register_read(offs_t offset)
+{
+ if (offset==0)
+ return ram_bank_cr & 0x03;
+
+ return rom_map_cr & 0x03;
+}
+
+void mc10_pak_mcx128_device::control_register_write(offs_t offset, u8 data)
+{
+ if (offset==0)
+ ram_bank_cr = data;
+ else
+ rom_map_cr = data;
+
+ update_banks();
+}
+
+void mc10_pak_mcx128_device::update_banks()
+{
+ int bank0 = ram_bank_cr & 0x01;
+ int bank1 = (ram_bank_cr & 0x02) >> 1;
+
+ m_bank[0]->set_entry(bank0);
+ m_bank[1]->set_entry(bank0);
+ m_bank[2]->set_entry(bank0);
+ m_bank[3]->set_entry(bank1);
+ m_bank[4]->set_entry(bank1);
+ m_bank[5]->set_entry(bank0);
+ m_bank[6]->set_entry(bank0);
+ m_bank[7]->set_entry(bank0);
+
+ m_view.select((bank1 << 2) | (rom_map_cr & 0x03));
+ LOG("view select: %d, bank cr: %d\n", (bank1 << 2) | (rom_map_cr & 0x03), ram_bank_cr & 0x03 );
+}
+
+class alice_pak_mcx128_device : public mc10_pak_mcx128_device
+{
+public:
+ // construction/destruction
+ alice_pak_mcx128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME(alice_mcx128);
+ }
+};
+
+//-------------------------------------------------
+// mc10_pak_device - constructor
+//-------------------------------------------------
+
+alice_pak_mcx128_device::alice_pak_mcx128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : mc10_pak_mcx128_device(mconfig, ALICE_PAK_MCX128, tag, owner, clock)
+{
+}
+
+DEFINE_DEVICE_TYPE_PRIVATE(ALICE_PAK_MCX128, device_mc10cart_interface, alice_pak_mcx128_device, "alice_mcx128", "Darren Atkinson's MCX-128 cartridge (Alice ROM)")