From c84a6b2530bb91c984b3d1ed33bac018baca8407 Mon Sep 17 00:00:00 2001 From: AJR Date: Sun, 9 Jun 2019 19:14:19 -0400 Subject: Make submaps work with address-shifted spaces (nw) Note that submaps are now assumed to use an address shift of 0. It is possible, though unlikely, for this to cause some breakage. --- src/emu/addrmap.cpp | 47 ++++++++++++++++++++++++++++++++++++++++------- src/emu/addrmap.h | 2 +- src/emu/emumem.cpp | 4 ++-- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/emu/addrmap.cpp b/src/emu/addrmap.cpp index 0a2e7a15c98..e1398013670 100644 --- a/src/emu/addrmap.cpp +++ b/src/emu/addrmap.cpp @@ -835,7 +835,7 @@ address_map_entry &address_map::operator()(offs_t start, offs_t end) // import_submaps - propagate in the device submaps //------------------------------------------------- -void address_map::import_submaps(running_machine &machine, device_t &owner, int data_width, endianness_t endian) +void address_map::import_submaps(running_machine &machine, device_t &owner, int data_width, endianness_t endian, int addr_shift) { address_map_entry *prev = nullptr; address_map_entry *entry = m_entrylist.first(); @@ -857,7 +857,7 @@ void address_map::import_submaps(running_machine &machine, device_t &owner, int address_map submap(*mapdevice, entry); // Recursively import if needed - submap.import_submaps(machine, *mapdevice, data_width, endian); + submap.import_submaps(machine, *mapdevice, data_width, endian, addr_shift); offs_t max_end = entry->m_addrend - entry->m_addrstart; @@ -867,6 +867,24 @@ void address_map::import_submaps(running_machine &machine, device_t &owner, int while (submap.m_entrylist.count()) { address_map_entry *subentry = submap.m_entrylist.detach_head(); + + if (addr_shift > 0) + { + subentry->m_addrstart <<= addr_shift; + subentry->m_addrend = ((subentry->m_addrend + 1) << addr_shift) - 1; + subentry->m_addrmirror <<= addr_shift; + subentry->m_addrmask <<= addr_shift; + subentry->m_addrselect <<= addr_shift; + } + else if (addr_shift < 0) + { + subentry->m_addrstart >>= -addr_shift; + subentry->m_addrend >>= -addr_shift; + subentry->m_addrmirror >>= -addr_shift; + subentry->m_addrmask >>= -addr_shift; + subentry->m_addrselect >>= -addr_shift; + } + if (subentry->m_addrend > max_end) subentry->m_addrend = max_end; @@ -895,6 +913,10 @@ void address_map::import_submaps(running_machine &machine, device_t &owner, int if ((entry->m_mask >> i) & 1) ratio ++; ratio = data_width / ratio; + if (addr_shift > 0) + ratio <<= addr_shift; + else if (addr_shift < 0) + max_end = ((max_end + 1) << -addr_shift) - 1; max_end = (max_end + 1) / ratio - 1; // Then merge the contents taking the ratio into account @@ -933,11 +955,22 @@ void address_map::import_submaps(running_machine &machine, device_t &owner, int if (subentry->m_addrend > max_end) subentry->m_addrend = max_end; - subentry->m_addrstart = subentry->m_addrstart * ratio + entry->m_addrstart; - subentry->m_addrend = (subentry->m_addrend + 1) * ratio - 1 + entry->m_addrstart; - subentry->m_addrmirror = (subentry->m_addrmirror / ratio) | entry->m_addrmirror; - subentry->m_addrmask = (subentry->m_addrmask / ratio) | entry->m_addrmask; - subentry->m_addrselect = (subentry->m_addrselect / ratio) | entry->m_addrselect; + if (addr_shift < 0) + { + subentry->m_addrstart = ((subentry->m_addrstart * ratio) >> -addr_shift) + entry->m_addrstart; + subentry->m_addrend = (((subentry->m_addrend + 1) * ratio - 1) >> -addr_shift) + entry->m_addrstart; + subentry->m_addrmirror = ((subentry->m_addrmirror / ratio) << -addr_shift) | entry->m_addrmirror; + subentry->m_addrmask = ((subentry->m_addrmask / ratio) << -addr_shift) | entry->m_addrmask; + subentry->m_addrselect = ((subentry->m_addrselect / ratio) << -addr_shift) | entry->m_addrselect; + } + else + { + subentry->m_addrstart = subentry->m_addrstart * ratio + entry->m_addrstart; + subentry->m_addrend = (subentry->m_addrend + 1) * ratio - 1 + entry->m_addrstart; + subentry->m_addrmirror = (subentry->m_addrmirror / ratio) | entry->m_addrmirror; + subentry->m_addrmask = (subentry->m_addrmask / ratio) | entry->m_addrmask; + subentry->m_addrselect = (subentry->m_addrselect / ratio) | entry->m_addrselect; + } if (subentry->m_addrstart > entry->m_addrend) { diff --git a/src/emu/addrmap.h b/src/emu/addrmap.h index 9256d22f65d..5a256c735fe 100644 --- a/src/emu/addrmap.h +++ b/src/emu/addrmap.h @@ -480,7 +480,7 @@ public: offs_t m_globalmask; // global mask simple_list m_entrylist; // list of entries - void import_submaps(running_machine &machine, device_t &owner, int data_width, endianness_t endian); + void import_submaps(running_machine &machine, device_t &owner, int data_width, endianness_t endian, int addr_shift); void map_validity_check(validity_checker &valid, int spacenum) const; }; diff --git a/src/emu/emumem.cpp b/src/emu/emumem.cpp index d5b53dda4b1..fc38a61a276 100644 --- a/src/emu/emumem.cpp +++ b/src/emu/emumem.cpp @@ -1235,7 +1235,7 @@ void address_space::prepare_map() m_map = std::make_unique(m_device, m_spacenum); // merge in the submaps - m_map->import_submaps(m_manager.machine(), m_device.owner() ? *m_device.owner() : m_device, data_width(), endianness()); + m_map->import_submaps(m_manager.machine(), m_device.owner() ? *m_device.owner() : m_device, data_width(), endianness(), addr_shift()); // extract global parameters specified by the map m_unmap = (m_map->m_unmapval == 0) ? 0 : ~0; @@ -1859,7 +1859,7 @@ template void address_space_speci { check_address("install_device_delegate", addrstart, addrend); address_map map(*this, addrstart, addrend, unitmask, cswidth, m_device, delegate); - map.import_submaps(m_manager.machine(), device, data_width(), endianness()); + map.import_submaps(m_manager.machine(), device, data_width(), endianness(), addr_shift()); populate_from_map(&map); } -- cgit v1.2.3