diff options
Diffstat (limited to 'src/mame/machine/315_5195.cpp')
-rw-r--r-- | src/mame/machine/315_5195.cpp | 612 |
1 files changed, 0 insertions, 612 deletions
diff --git a/src/mame/machine/315_5195.cpp b/src/mame/machine/315_5195.cpp deleted file mode 100644 index 698909cbc7e..00000000000 --- a/src/mame/machine/315_5195.cpp +++ /dev/null @@ -1,612 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -/*************************************************************************** - - Sega 315-5195 memory mapper - -***************************************************************************/ - -#include "emu.h" -#include "315_5195.h" - -#include <algorithm> - -//************************************************************************** -// DEBUGGING -//************************************************************************** - -#define VERBOSE (0) - -#include "logmacro.h" - - - -//************************************************************************** -// CONSTANTS -//************************************************************************** - -// device type definition -DEFINE_DEVICE_TYPE(SEGA_315_5195_MEM_MAPPER, sega_315_5195_mapper_device, "sega_315_5195", "Sega 315-5195 Memory Mapper") - - - -//************************************************************************** -// 315-5195 MEMORY MAPPER -//************************************************************************** - -//------------------------------------------------- -// sega_315_5195_mapper_device - constructor -//------------------------------------------------- - -sega_315_5195_mapper_device::sega_315_5195_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : device_t(mconfig, SEGA_315_5195_MEM_MAPPER, tag, owner, clock) - , m_cpu(*this, finder_base::DUMMY_TAG) - , m_cpuregion(*this, finder_base::DUMMY_TAG) - , m_mapper(*this) - , m_pbf_callback(*this) - , m_mcu_int_callback(*this) - , m_space(nullptr) - , m_decrypted_space(nullptr) - , m_curregion(0) - , m_to_sound(0) - , m_from_sound(0) - , m_open_bus_recurse(false) -{ -} - - -//------------------------------------------------- -// open_bus_r - return value from reading an -// unmapped address -//------------------------------------------------- - -u16 sega_315_5195_mapper_device::open_bus_r() -{ - // Unmapped memory returns the last word on the data bus, which is almost always the opcode - // of the next instruction due to prefetch; however, since we may be encrypted, we actually - // need to return the encrypted opcode, not the last decrypted data. - - // Believe it or not, this is actually important for Cotton, which has the following evil - // code: btst #0,$7038f7, which tests the low bit of an unmapped address, which thus should - // return the prefetched value. - - // prevent recursion - if (!machine().side_effects_disabled()) - { - if (m_open_bus_recurse) - return 0xffff; - - // read original encrypted memory at that address - m_open_bus_recurse = true; - const u16 result = m_space->read_word(m_cpu->pc()); - m_open_bus_recurse = false; - return result; - } - return 0xffff; -} - - -//------------------------------------------------- -// write - handle a write to the memory mapper -//------------------------------------------------- - -void sega_315_5195_mapper_device::write(offs_t offset, u8 data) -{ - // wraps every 32 bytes - offset &= 0x1f; - - LOG("(Write %02X = %02X)\n", offset, data); - - // remember the previous value and swap in the new one - const u8 oldval = m_regs[offset]; - m_regs[offset] = data; - - // switch off the offset - switch (offset) - { - case 0x02: - // misc commands - // 00 - resume execution after 03 - // 03 - maybe controls halt and reset lines together? - if ((oldval ^ m_regs[offset]) & 3) - { - // fd1094_machine_init calls device_reset on the CPU, so we must do this afterwards - m_cpu->set_input_line(INPUT_LINE_RESET, (m_regs[offset] & 3) == 3 ? ASSERT_LINE : CLEAR_LINE); - } - break; - - case 0x03: - // write through to the sound chip - machine().scheduler().synchronize(timer_expired_delegate(FUNC(sega_315_5195_mapper_device::write_to_sound), this), data); - break; - - case 0x04: - // controls IRQ lines to 68000, negative logic -- write $B to signal IRQ4 - if ((m_regs[offset] & 7) != 7) - for (int irqnum = 0; irqnum < 8; irqnum++) - m_cpu->set_input_line(irqnum, (irqnum == (~m_regs[offset] & 7)) ? HOLD_LINE : CLEAR_LINE); - break; - - case 0x05: - // read/write control - // 01 - write data latched in 00,01 to 2 * (address in 0A,0B,0C) - // 02 - read data into latches 00,01 from 2 * (address in 07,08,09) - if (data == 0x01) - { - const offs_t addr = (m_regs[0x0a] << 17) | (m_regs[0x0b] << 9) | (m_regs[0x0c] << 1); - m_space->write_word(addr, (m_regs[0x00] << 8) | m_regs[0x01]); - } - else if (data == 0x02) - { - const offs_t addr = (m_regs[0x07] << 17) | (m_regs[0x08] << 9) | (m_regs[0x09] << 1); - const u16 result = m_space->read_word(addr); - m_regs[0x00] = result >> 8; - m_regs[0x01] = result; - } - break; - - case 0x07: case 0x08: case 0x09: - // writes here latch a 68000 address for writing - break; - - case 0x0a: case 0x0b: case 0x0c: - // writes here latch a 68000 address for reading - break; - - case 0x10: case 0x11: - case 0x12: case 0x13: - case 0x14: case 0x15: - case 0x16: case 0x17: - case 0x18: case 0x19: - case 0x1a: case 0x1b: - case 0x1c: case 0x1d: - case 0x1e: case 0x1f: - if (oldval != data) - update_mapping(); - break; - - default: - logerror("Unknown memory_mapper_w to address %02X = %02X\n", offset, data); - break; - } -} - - -//------------------------------------------------- -// read - handle a read from the memory mapper -//------------------------------------------------- - -u8 sega_315_5195_mapper_device::read(address_space &space, offs_t offset) -{ - // wraps every 32 bytes - offset &= 0x1f; - - // switch off the offset - switch (offset) - { - case 0x00: - case 0x01: - // data latches - return the values latched - return m_regs[offset]; - - case 0x02: - // various input bits from the 68000 - // 01 - ???? - // 02 - ???? - // 04 - ???? - // 08 - ???? - // 40 - set if busy processing a read/write request - // Together, 01+02 == 00 if the 68000 is halted - // Together, 01+02+04+08 == 0F if the 68000 is executing - return (m_regs[0x02] & 3) == 3 ? 0x00 : 0x0f; - - case 0x03: - // this returns data that the sound CPU writes - if (!m_mcu_int_callback.isnull() && !machine().side_effects_disabled()) - m_mcu_int_callback(CLEAR_LINE); - return m_from_sound; - - default: - logerror("Unknown memory_mapper_r from address %02X\n", offset); - break; - } - return (space.data_width() == 8) ? 0xff : open_bus_r(); -} - - -//------------------------------------------------- -// map_as_rom - map a region as ROM data -//------------------------------------------------- - -void sega_315_5195_mapper_device::map_as_rom(u32 offset, u32 length, offs_t mirror, const char *bank_name, const char *decrypted_bank_name, offs_t rgnoffset, write16_delegate whandler) -{ - // determine parameters - region_info info; - compute_region(info, m_curregion, length, mirror, offset); - LOG("Map %06X-%06X (%06X) as ROM+%06X(%s) with handler=%s\n", info.start, info.end, info.mirror, rgnoffset, bank_name, - whandler.isnull() ? "none" : whandler.name()); - - // don't map if the start is past the end of the ROM region - const offs_t romsize = m_cpuregion->bytes(); - if (rgnoffset < romsize) - { - // clamp the end to the ROM size - offs_t romend = info.end; - if (rgnoffset + romend + 1 - info.start >= romsize) - romend = romsize - 1 - rgnoffset + info.start; - - // map now - m_space->install_read_bank(info.start, romend, info.mirror, bank_name); - if (m_decrypted_space) - m_decrypted_space->install_read_bank(info.start, romend, info.mirror, decrypted_bank_name); - - // configure the bank - memory_bank *bank = owner()->membank(bank_name); - memory_bank *decrypted_bank = owner()->membank(decrypted_bank_name); - u8 *memptr = m_cpuregion->base() + rgnoffset; - bank->set_base(memptr); - - // remember this bank, and decrypt if necessary - m_banks[m_curregion].set(bank, decrypted_bank, info.start, romend, rgnoffset, memptr); - } - - // either install a write handler if provided or unmap the region - // - // shdancer relies on this behaviour to prevent a write to ROM from - // falling through to the memory-mapping registers and crashing the - // game during stage 2-4 (see PC:$18a98). Protection maybe? - if (!whandler.isnull()) - m_space->install_write_handler(info.start, info.end, 0, info.mirror, 0, whandler); - else - m_space->unmap_write(info.start, info.end | info.mirror); -} - - -//------------------------------------------------- -// map_as_ram - map a region as RAM, with an -// optional write handler -//------------------------------------------------- - -void sega_315_5195_mapper_device::map_as_ram(u32 offset, u32 length, offs_t mirror, const char *bank_share_name, write16_delegate whandler) -{ - // determine parameters - region_info info; - compute_region(info, m_curregion, length, mirror, offset); - LOG("Map %06X-%06X (%06X) as RAM(%s) with handler=%s\n", info.start, info.end, info.mirror, bank_share_name, - whandler.isnull() ? "none" : whandler.name()); - - // map now - m_space->install_read_bank(info.start, info.end, info.mirror, bank_share_name); - - // either install a write handler or a write bank, as appropriate - if (!whandler.isnull()) - m_space->install_write_handler(info.start, info.end, 0, info.mirror, 0, whandler); - else - m_space->install_write_bank(info.start, info.end, info.mirror, bank_share_name); - - // configure the bank - memory_bank *bank = owner()->membank(bank_share_name); - bank->set_base(owner()->memshare(bank_share_name)->ptr()); - - // clear this rom bank reference - m_banks[m_curregion].clear(); -} - - -//------------------------------------------------- -// map_as_handler - map a region as a pair of -// read write handlers -//------------------------------------------------- - -void sega_315_5195_mapper_device::map_as_handler(u32 offset, u32 length, offs_t mirror, read16_delegate rhandler, write16_delegate whandler) -{ - // determine parameters - region_info info; - compute_region(info, m_curregion, length, mirror, offset); - LOG("Map %06X-%06X (%06X) as handler read=%s write=%s\n", info.start, info.end, info.mirror, - rhandler.isnull() ? "none" : rhandler.name(), - whandler.isnull() ? "none" : whandler.name()); - - // install read/write handlers - if (!rhandler.isnull()) - m_space->install_read_handler(info.start, info.end, 0, info.mirror, 0, rhandler); - if (!whandler.isnull()) - m_space->install_write_handler(info.start, info.end, 0, info.mirror, 0, whandler); - - // clear this rom bank reference - m_banks[m_curregion].clear(); -} - - -//------------------------------------------------- -// configure_explicit - explicitly configure the -// memory map -//------------------------------------------------- - -void sega_315_5195_mapper_device::configure_explicit(const u8 *map_data) -{ - memcpy(&m_regs[0x10], map_data, 0x10); - update_mapping(); -} - - -//------------------------------------------------- -// fd1094_state_change - handle notifications -// of state changes -//------------------------------------------------- - -void sega_315_5195_mapper_device::fd1094_state_change(u8 state) -{ - // iterate over regions and set the decrypted address of any ROM banks - for (auto & elem : m_banks) - elem.update(); -} - - -//------------------------------------------------- -// write_to_sound - write data for the sound CPU -//------------------------------------------------- - -TIMER_CALLBACK_MEMBER(sega_315_5195_mapper_device::write_to_sound) -{ - m_to_sound = param; - if (!m_pbf_callback.isnull()) - m_pbf_callback(ASSERT_LINE); -} - - -//------------------------------------------------- -// write_from_sound - handle writes from the -// sound CPU -//------------------------------------------------- - -TIMER_CALLBACK_MEMBER(sega_315_5195_mapper_device::write_from_sound) -{ - m_from_sound = param; - if (!m_mcu_int_callback.isnull()) - m_mcu_int_callback(ASSERT_LINE); -} - - -//------------------------------------------------- -// pread - sound CPU read handler -//------------------------------------------------- - -u8 sega_315_5195_mapper_device::pread() -{ - if (!m_pbf_callback.isnull() && !machine().side_effects_disabled()) - m_pbf_callback(CLEAR_LINE); - return m_to_sound; -} - - -//------------------------------------------------- -// pwrite - sound CPU write handler -//------------------------------------------------- - -void sega_315_5195_mapper_device::pwrite(u8 data) -{ - machine().scheduler().synchronize(timer_expired_delegate(FUNC(sega_315_5195_mapper_device::write_from_sound), this), data); -} - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sega_315_5195_mapper_device::device_start() -{ - // bind our handlers - m_mapper.resolve(); - m_pbf_callback.resolve(); - m_mcu_int_callback.resolve(); - - // if we are mapping an FD1089, tell all the banks - fd1089_base_device *fd1089 = dynamic_cast<fd1089_base_device *>(m_cpu.target()); - if (fd1089 != nullptr) - for (auto & elem : m_banks) - elem.set_decrypt(fd1089); - - // if we are mapping an FD1094, register for state change notifications and tell all the banks - fd1094_device *fd1094 = dynamic_cast<fd1094_device *>(m_cpu.target()); - if (fd1094 != nullptr) - { - fd1094->notify_state_change(fd1094_device::state_change_delegate(&sega_315_5195_mapper_device::fd1094_state_change, this)); - for (auto & elem : m_banks) - elem.set_decrypt(fd1094); - } - - // find the address space that is to be mapped - m_space = &m_cpu->space(AS_PROGRAM); - if (m_space == nullptr) - throw emu_fatalerror("Unable to find program address space on device '%s'", m_cpu.finder_tag()); - - m_decrypted_space = m_cpu->has_space(AS_OPCODES) ? &m_cpu->space(AS_OPCODES) : nullptr; - - // register for saves - save_item(NAME(m_regs)); - save_item(NAME(m_to_sound)); - save_item(NAME(m_from_sound)); -} - - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void sega_315_5195_mapper_device::device_reset() -{ - // hold the CPU in reset - m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - - // clear registers and recompute the memory mapping - std::fill(std::begin(m_regs), std::end(m_regs), 0); - update_mapping(); - - // release the CPU - m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); - - m_to_sound = 0; - m_from_sound = 0; - if (!m_pbf_callback.isnull()) - m_pbf_callback(CLEAR_LINE); - if (!m_mcu_int_callback.isnull()) - m_mcu_int_callback(CLEAR_LINE); -} - - -//------------------------------------------------- -// compute_region - determine region parameters -// based on current configuration registers and -// actual underlying bus connections -//------------------------------------------------- - -void sega_315_5195_mapper_device::compute_region(region_info &info, u8 index, u32 length, u32 mirror, u32 offset) -{ - static const offs_t region_size_map[4] = { 0x00ffff, 0x01ffff, 0x07ffff, 0x1fffff }; - info.size_mask = region_size_map[m_regs[0x10 + 2 * index] & 3]; - info.base = (m_regs[0x11 + 2 * index] << 16) & ~info.size_mask; - info.mirror = mirror & info.size_mask; - info.start = info.base + (offset & info.size_mask); - info.end = info.start + std::min(length - 1, info.size_mask); -} - - -//------------------------------------------------- -// update_mapping - remap the entire CPU address -// space based on updated mappings -//------------------------------------------------- - -void sega_315_5195_mapper_device::update_mapping() -{ - LOG("---- Remapping:\n"); - - // first reset everything back to the beginning - m_space->unmap_readwrite(0x000000, 0xffffff); - m_space->install_read_handler(0x000000, 0xffffff, read8m_delegate(*this, FUNC(sega_315_5195_mapper_device::read)), 0x00ff); - m_space->install_write_handler(0x000000, 0xffffff, write8sm_delegate(*this, FUNC(sega_315_5195_mapper_device::write)), 0x00ff); - - // loop over the regions - for (int index = 7; index >= 0; index--) - { - // note the current region and call the mapper to find out what to do - m_curregion = index; - m_mapper(*this, index); - } -} - - -//************************************************************************** -// DECRYPT BANK HELPER CLASS -//************************************************************************** - -//------------------------------------------------- -// decrypt_bank - constructor -//------------------------------------------------- - -sega_315_5195_mapper_device::decrypt_bank::decrypt_bank() - : m_bank(nullptr) - , m_decrypted_bank(nullptr) - , m_start(0) - , m_end(0) - , m_rgnoffs(~0) - , m_srcptr(nullptr) - , m_fd1089(nullptr) -{ - // invalidate all states - reset(); -} - - -//------------------------------------------------- -// ~decrypt_bank - destructor -//------------------------------------------------- - -sega_315_5195_mapper_device::decrypt_bank::~decrypt_bank() -{ -} - - -//------------------------------------------------- -// set_decrypt - configure the decryption target -// CPU -//------------------------------------------------- - -void sega_315_5195_mapper_device::decrypt_bank::set_decrypt(fd1089_base_device *fd1089) -{ - // set the fd1089 pointer - m_fd1089 = fd1089; - - // clear out all fd1094 stuff - m_fd1094_cache.reset(); -} - -void sega_315_5195_mapper_device::decrypt_bank::set_decrypt(fd1094_device *fd1094) -{ - // set the fd1094 pointer and allocate a decryption cache - m_fd1094_cache = std::make_unique<fd1094_decryption_cache>(*fd1094); - - // clear out all fd1089 stuff - m_fd1089 = nullptr; - m_fd1089_decrypted.clear(); -} - - -//------------------------------------------------- -// set - set the parameters of this bank after -// a change -//------------------------------------------------- - -void sega_315_5195_mapper_device::decrypt_bank::set(memory_bank *bank, memory_bank *decrypted_bank, offs_t start, offs_t end, offs_t rgnoffs, u8 *src) -{ - // ignore if not encrypted - if (m_fd1089 == nullptr && m_fd1094_cache == nullptr) - return; - - // ignore if nothing is changing - if (bank == m_bank && start == m_start && end == m_end && rgnoffs == m_rgnoffs && src == m_srcptr) - return; - - // if the start, end, or src change, throw away any cached data - reset(); - - // update to the current state - m_bank = bank; - m_decrypted_bank = decrypted_bank; - m_start = start; - m_end = end; - m_rgnoffs = rgnoffs; - m_srcptr = src; - - // configure the fd1094 cache - if (m_fd1094_cache != nullptr) - m_fd1094_cache->configure(m_start, m_end + 1 - m_start, m_rgnoffs); - - // force an update of what we have - update(); -} - - -//------------------------------------------------- -// update - update the decrypted memory base -// if this rom bank has been assigned -//------------------------------------------------- - -void sega_315_5195_mapper_device::decrypt_bank::update() -{ - // if this isn't a valid state, don't try to do anything - if (m_bank == nullptr || m_srcptr == nullptr) - return; - - // fd1089 case - if (m_fd1089 != nullptr) - { - m_fd1089_decrypted.resize((m_end + 1 - m_start) / 2); - m_fd1089->decrypt(m_start, m_end + 1 - m_start, m_rgnoffs, &m_fd1089_decrypted[0], reinterpret_cast<u16 *>(m_srcptr)); - m_decrypted_bank->set_base(&m_fd1089_decrypted[0]); - } - - // fd1094 case - if (m_fd1094_cache != nullptr) - m_decrypted_bank->set_base(m_fd1094_cache->decrypted_opcodes(m_fd1094_cache->fd1094().state())); -} |