diff options
Diffstat (limited to 'src/devices/bus/a800/sparta.cpp')
| -rw-r--r-- | src/devices/bus/a800/sparta.cpp | 178 |
1 files changed, 147 insertions, 31 deletions
diff --git a/src/devices/bus/a800/sparta.cpp b/src/devices/bus/a800/sparta.cpp index 8b8242d8dad..f4e6e69e25f 100644 --- a/src/devices/bus/a800/sparta.cpp +++ b/src/devices/bus/a800/sparta.cpp @@ -1,73 +1,189 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli -/*********************************************************************************************************** +// copyright-holders:Fabio Priuli, Angelo Salese +/************************************************************************************************** - A800 SpartaDOS cart emulation +SpartaDOS X (SDX) cart emulation -***********************************************************************************************************/ +https://sdx.atari8.info/index.php?show=en_introduction +SDX 128KB a newer format used by the 200x releases: adds an extra bank access to $d5f0-$d5f7. +Should mirror $e8-$ef to $fx by logic. + +**************************************************************************************************/ #include "emu.h" #include "sparta.h" - +#include "a800_carts.h" //------------------------------------------------- // constructor //------------------------------------------------- -DEFINE_DEVICE_TYPE(A800_ROM_SPARTADOS, a800_rom_spartados_device, "a800_sparta", "Atari 800 SpartaDOS ROM Carts") +DEFINE_DEVICE_TYPE(A800_ROM_SPARTADOS, a800_rom_spartados_device, "a800_sparta", "Atari 8-bit SpartaDOS X cart") +DEFINE_DEVICE_TYPE(A800_ROM_SPARTADOS_128KB, a800_rom_spartados_128kb_device, "a800_sparta_128kb", "Atari 8-bit SpartaDOS X 128KB cart") +a800_rom_spartados_device::a800_rom_spartados_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, type, tag, owner, clock) + , m_bank(0) + , m_subcart(*this, "subcart") + , m_cart_view(*this, "cart_view") +{ + +} a800_rom_spartados_device::a800_rom_spartados_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A800_ROM_SPARTADOS, tag, owner, clock) - , m_bank(0) - , m_subslot_enabled(0) + : a800_rom_spartados_device(mconfig, A800_ROM_SPARTADOS, tag, owner, clock) { } +static void spartados_carts(device_slot_interface &device) +{ + // NB: game carts will usually override SDX boot, meaning that they aren't all that useful to hook up here. + // also a SDX attached to another SDX just produces a black screen. + // we just hook them all up for the sake of completeness. + a800_left(device); +} +void a800_rom_spartados_device::subcart_rd4_w(int state) +{ + m_subcart_rd4_enabled = state; + if (m_subcart_enabled) + { + rd4_w(m_subcart_rd4_enabled); + rd5_w(m_subcart_rd5_enabled); + } +} + +void a800_rom_spartados_device::subcart_rd5_w(int state) +{ + m_subcart_rd5_enabled = state; + if (m_subcart_enabled) + { + rd4_w(m_subcart_rd4_enabled); + rd5_w(m_subcart_rd5_enabled); + } +} + +void a800_rom_spartados_device::device_add_mconfig(machine_config &config) +{ + A800_CART_SLOT(config, m_subcart, spartados_carts, nullptr); + m_subcart->rd4_callback().set(FUNC(a800_rom_spartados_device::subcart_rd4_w)); + m_subcart->rd5_callback().set(FUNC(a800_rom_spartados_device::subcart_rd5_w)); +} void a800_rom_spartados_device::device_start() { save_item(NAME(m_bank)); - save_item(NAME(m_subslot_enabled)); + save_item(NAME(m_subcart_enabled)); } void a800_rom_spartados_device::device_reset() { - m_bank = 0; - m_subslot_enabled = 0; + m_bank = 7; + m_subcart_enabled = false; + if (!m_subcart->exists()) + m_subcart_rd4_enabled = m_subcart_rd5_enabled = 0; + else + std::tie(m_subcart_rd4_enabled, m_subcart_rd5_enabled) = m_subcart->get_initial_rd_state(); + + m_cart_view.select(0); } -/*------------------------------------------------- - mapper specific handlers - -------------------------------------------------*/ +void a800_rom_spartados_device::cart_map(address_map &map) +{ + map(0x0000, 0x3fff).view(m_cart_view); + m_cart_view[0](0x2000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; }) + ); + m_cart_view[1](0x0000, 0x1fff).rw(m_subcart, FUNC(a800_cart_slot_device::read_cart<0>), FUNC(a800_cart_slot_device::write_cart<0>)); + m_cart_view[1](0x2000, 0x3fff).rw(m_subcart, FUNC(a800_cart_slot_device::read_cart<1>), FUNC(a800_cart_slot_device::write_cart<1>)); +} -/*------------------------------------------------- +void a800_rom_spartados_device::cctl_map(address_map &map) +{ + map(0x00, 0xff).rw(m_subcart, FUNC(a800_cart_slot_device::read_cctl), FUNC(a800_cart_slot_device::write_cctl)); + map(0xe0, 0xe7).rw(FUNC(a800_rom_spartados_device::rom_bank_r), FUNC(a800_rom_spartados_device::rom_bank_w)); + map(0xe8, 0xef).rw(FUNC(a800_rom_spartados_device::subslot_r), FUNC(a800_rom_spartados_device::subslot_w)); +} - SpartaDOS 64K carts +inline void a800_rom_spartados_device::bank_config_access(offs_t offset) +{ + rd4_w(0); + rd5_w(1); + m_cart_view.select(0); + m_bank = ((offset ^ m_bank_mask) & m_bank_mask); + m_subcart_enabled = false; +} - Similar to Express / Diamond carts, because - bankswitch is controlled by writing to 7 diff - offsets in reverse order, but writes to offsets - 0x8-0xf also enable/disable subslot +uint8_t a800_rom_spartados_device::rom_bank_r(offs_t offset) +{ + if(!machine().side_effects_disabled()) + bank_config_access(offset); - -------------------------------------------------*/ + return m_subcart->read_cctl(offset | 0xe0); +} -uint8_t a800_rom_spartados_device::read_80xx(offs_t offset) +void a800_rom_spartados_device::rom_bank_w(offs_t offset, uint8_t data) { - if (!m_subslot_enabled) - return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; - else - return 0xff; // subslot, currently not implemented + bank_config_access(offset); + m_subcart->write_cctl(offset | 0xe0, data); } -void a800_rom_spartados_device::write_d5xx(offs_t offset, uint8_t data) +inline void a800_rom_spartados_device::subslot_config_access(offs_t offset) { - if (offset & 0x08) - m_subslot_enabled = !BIT(offset, 2); + if (!BIT(offset, 2)) + { + m_subcart_enabled = true; + rd4_w(m_subcart_rd4_enabled); + rd5_w(m_subcart_rd5_enabled); + m_cart_view.select(1); + } else - m_bank = (offset ^ 0x07) & 0x0f; + { + m_subcart_enabled = false; + rd4_w(0); + rd5_w(0); + } +} + +u8 a800_rom_spartados_device::subslot_r(offs_t offset) +{ + if(!machine().side_effects_disabled()) + subslot_config_access(offset); + + return m_subcart->read_cctl(offset | 0xe8); +} + +void a800_rom_spartados_device::subslot_w(offs_t offset, u8 data) +{ + subslot_config_access(offset); + + return m_subcart->write_cctl(offset | 0xe8, data); +} + +/*------------------------------------------------- + + SpartaDOS 128KB variant + -------------------------------------------------*/ + +a800_rom_spartados_128kb_device::a800_rom_spartados_128kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_spartados_device(mconfig, A800_ROM_SPARTADOS_128KB, tag, owner, clock) +{ +} + +// NB: .select not .mirror, we need the offset to propagate to sub cart cctl +void a800_rom_spartados_128kb_device::cctl_map(address_map &map) +{ + a800_rom_spartados_device::cctl_map(map); + map(0xe0, 0xe7).select(0x10).rw(FUNC(a800_rom_spartados_128kb_device::rom_bank_r), FUNC(a800_rom_spartados_128kb_device::rom_bank_w)); + map(0xe8, 0xef).select(0x10).rw(FUNC(a800_rom_spartados_128kb_device::subslot_r), FUNC(a800_rom_spartados_128kb_device::subslot_w)); +} + +inline void a800_rom_spartados_128kb_device::bank_config_access(offs_t offset) +{ + a800_rom_spartados_device::bank_config_access(offset); + const u8 upper_bank = !BIT(offset, 4); + m_bank = ((offset ^ 7) & 7) | (upper_bank << 3); } |
