summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2019-06-09 19:14:19 -0400
committer AJR <ajrhacker@users.noreply.github.com>2019-06-09 19:26:41 -0400
commitc84a6b2530bb91c984b3d1ed33bac018baca8407 (patch)
treea81b46af7f935473ddda402975f518cb5d3acaed
parenta610524c5f8907897905ce109fc714b2201183de (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.
-rw-r--r--src/emu/addrmap.cpp47
-rw-r--r--src/emu/addrmap.h2
-rw-r--r--src/emu/emumem.cpp4
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);
}