summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/addrmap.cpp
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 /src/emu/addrmap.cpp
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.
Diffstat (limited to 'src/emu/addrmap.cpp')
-rw-r--r--src/emu/addrmap.cpp47
1 files changed, 40 insertions, 7 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)
{