summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/315_5195.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/315_5195.cpp')
-rw-r--r--src/mame/machine/315_5195.cpp612
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()));
-}