diff options
Diffstat (limited to 'src/devices/bus/pce/pce_acard.cpp')
-rw-r--r-- | src/devices/bus/pce/pce_acard.cpp | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/src/devices/bus/pce/pce_acard.cpp b/src/devices/bus/pce/pce_acard.cpp new file mode 100644 index 00000000000..833f78e9536 --- /dev/null +++ b/src/devices/bus/pce/pce_acard.cpp @@ -0,0 +1,232 @@ +// license:BSD-3-Clause +// copyright-holders:Fabio Priuli, Angelo Salese +/*********************************************************************************************************** + + + PC-Engine Arcade Card emulation + + TODO: + - Proper Arcade Card Duo support + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "pce_acard.h" + + + +//------------------------------------------------- +// pce_acard_device - constructor +//------------------------------------------------- + +DEFINE_DEVICE_TYPE(PCE_ROM_ACARD_DUO, pce_acard_duo_device, "pce_acard_duo", "Arcade Card Duo") +DEFINE_DEVICE_TYPE(PCE_ROM_ACARD_PRO, pce_acard_pro_device, "pce_acard_pro", "Arcade Card Pro") + + +pce_acard_duo_device::pce_acard_duo_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_pce_cart_interface( mconfig, *this ) + , m_ram(*this, "ram", 0x200000, ENDIANNESS_LITTLE) + , m_shift(0) + , m_shift_reg(0) + , m_rotate_reg(0) +{ +} + +pce_acard_duo_device::pce_acard_duo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : pce_acard_duo_device(mconfig, PCE_ROM_ACARD_DUO, tag, owner, clock) +{ +} + +pce_acard_pro_device::pce_acard_pro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : pce_acard_duo_device(mconfig, PCE_ROM_ACARD_PRO, tag, owner, clock) + , m_scdsys() +{ +} + + +//------------------------------------------------- +// mapper specific start/reset +//------------------------------------------------- + + +void pce_acard_duo_device::device_start() +{ + save_item(STRUCT_MEMBER(m_port, m_ctrl)); + save_item(STRUCT_MEMBER(m_port, m_base_addr)); + save_item(STRUCT_MEMBER(m_port, m_addr_offset)); + save_item(STRUCT_MEMBER(m_port, m_addr_inc)); + save_item(NAME(m_shift)); + save_item(NAME(m_shift_reg)); + save_item(NAME(m_rotate_reg)); +} + +void pce_acard_pro_device::device_start() +{ + pce_acard_duo_device::device_start(); + + m_scdsys.init(*this); + m_scdsys.set_region(false); +} + +void pce_acard_duo_device::device_reset() +{ + for (auto &port : m_port) + { + port.m_ctrl = 0; + port.m_base_addr = 0; + port.m_addr_offset = 0; + port.m_addr_inc = 0; + } + m_shift = 0; + m_shift_reg = 0; + m_rotate_reg = 0; +} + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +void pce_acard_duo_device::install_memory_handlers(address_space &space) +{ + space.install_readwrite_handler(0x080000, 0x087fff, emu::rw_delegate(*this, FUNC(pce_acard_duo_device::ram_r)), emu::rw_delegate(*this, FUNC(pce_acard_duo_device::ram_w))); + // TODO: mirrored? + space.install_readwrite_handler(0x1ffa00, 0x1ffaff, 0, 0x100, 0, emu::rw_delegate(*this, FUNC(pce_acard_duo_device::peripheral_r)), emu::rw_delegate(*this, FUNC(pce_acard_duo_device::peripheral_w))); +} + +void pce_acard_pro_device::install_memory_handlers(address_space &space) +{ + space.install_rom(0x000000, 0x03ffff, 0x040000, m_rom); // TODO: underdumped or mirrored? + space.install_ram(0x0d0000, 0x0fffff, m_scdsys.ram()); + space.install_read_handler(0x1ff8c0, 0x1ff8c7, 0, 0x130, 0, emu::rw_delegate(*this, FUNC(pce_acard_pro_device::register_r))); + pce_acard_duo_device::install_memory_handlers(space); +} + +uint8_t pce_acard_duo_device::ram_r(offs_t offset) +{ + return peripheral_r((offset & 0x6000) >> 9); +} + +void pce_acard_duo_device::ram_w(offs_t offset, uint8_t data) +{ + peripheral_w((offset & 0x6000) >> 9, data); +} + +uint8_t pce_acard_duo_device::peripheral_r(offs_t offset) +{ + if ((offset & 0xe0) == 0xe0) + { + switch (offset & 0x1f) + { + case 0x00: return (m_shift >> 0) & 0xff; + case 0x01: return (m_shift >> 8) & 0xff; + case 0x02: return (m_shift >> 16) & 0xff; + case 0x03: return (m_shift >> 24) & 0xff; + case 0x04: return m_shift_reg; + case 0x05: return m_rotate_reg; + case 0x1c: return 0x00; + case 0x1d: return 0x00; + case 0x1e: return 0x10; // Version number (MSB?) + case 0x1f: return 0x51; // Arcade Card ID + } + + return 0xff; + } + + dram_port &port = m_port[(offset & 0x30) >> 4]; + + switch (offset & 0x8f) + { + case 0x00: + case 0x01: + { + uint8_t const res = m_ram[port.ram_addr()]; + + if (!machine().side_effects_disabled()) + port.addr_increment(); + + return res; + } + case 0x02: return (port.m_base_addr >> 0) & 0xff; + case 0x03: return (port.m_base_addr >> 8) & 0xff; + case 0x04: return (port.m_base_addr >> 16) & 0xff; + case 0x05: return (port.m_addr_offset >> 0) & 0xff; + case 0x06: return (port.m_addr_offset >> 8) & 0xff; + case 0x07: return (port.m_addr_inc >> 0) & 0xff; + case 0x08: return (port.m_addr_inc >> 8) & 0xff; + case 0x09: return port.m_ctrl; + default: return 0xff; + } +} + +void pce_acard_duo_device::peripheral_w(offs_t offset, uint8_t data) +{ + if ((offset & 0xe0) == 0xe0) + { + switch (offset & 0x0f) + { + case 0: m_shift = (data & 0xff) | (m_shift & 0xffffff00); break; + case 1: m_shift = (data << 8) | (m_shift & 0xffff00ff); break; + case 2: m_shift = (data << 16) | (m_shift & 0xff00ffff); break; + case 3: m_shift = (data << 24) | (m_shift & 0x00ffffff); break; + case 4: + m_shift_reg = data & 0x0f; + + if (m_shift_reg != 0) + { + m_shift = (m_shift_reg < 8) + ? (m_shift << m_shift_reg) + : (m_shift >> (16 - m_shift_reg)); + } + break; + case 5: + m_rotate_reg = data & 0x0f; + + if (m_rotate_reg != 0) + { + m_shift = (m_rotate_reg < 8) + ? ((m_shift << m_rotate_reg) | (m_shift >> (32 - m_rotate_reg))) + : ((m_shift >> (16 - m_rotate_reg)) | (m_shift << (32 - (16 - m_rotate_reg)))); + } + break; + } + } + else + { + dram_port &port = m_port[(offset & 0x30) >> 4]; + + switch (offset & 0x8f) + { + case 0x00: + case 0x01: + m_ram[port.ram_addr()] = data; + + port.addr_increment(); + break; + + case 0x02: port.m_base_addr = (data & 0xff) | (port.m_base_addr & 0xffff00); break; + case 0x03: port.m_base_addr = (data << 8) | (port.m_base_addr & 0xff00ff); break; + case 0x04: port.m_base_addr = (data << 16) | (port.m_base_addr & 0x00ffff); break; + case 0x05: + port.m_addr_offset = (data & 0xff) | (port.m_addr_offset & 0xff00); + + if ((port.m_ctrl & 0x60) == 0x20) + port.adjust_addr(); + break; + case 0x06: + port.m_addr_offset = (data << 8) | (port.m_addr_offset & 0x00ff); + + if ((port.m_ctrl & 0x60) == 0x40) + port.adjust_addr(); + break; + case 0x07: port.m_addr_inc = (data & 0xff) | (port.m_addr_inc & 0xff00); break; + case 0x08: port.m_addr_inc = (data << 8) | (port.m_addr_inc & 0x00ff); break; + case 0x09: port.m_ctrl = data & 0x7f; break; + case 0x0a: + if ((port.m_ctrl & 0x60) == 0x60) + port.adjust_addr(); + break; + } + } +} |