summaryrefslogtreecommitdiffstatshomepage
path: root/src
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
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')
-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);
}