diff options
Diffstat (limited to 'src/devices/bus/mc10/mcx128.cpp')
-rw-r--r-- | src/devices/bus/mc10/mcx128.cpp | 371 |
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)") |