diff options
author | 2019-06-09 19:14:19 -0400 | |
---|---|---|
committer | 2019-06-09 19:26:41 -0400 | |
commit | c84a6b2530bb91c984b3d1ed33bac018baca8407 (patch) | |
tree | a81b46af7f935473ddda402975f518cb5d3acaed /src | |
parent | a610524c5f8907897905ce109fc714b2201183de (diff) |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/emu/addrmap.cpp | 47 | ||||
-rw-r--r-- | src/emu/addrmap.h | 2 | ||||
-rw-r--r-- | 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<address_map_entry> 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<address_map>(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<int Width, int AddrShift, endianness_t Endian> 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); } |