summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2017-03-25 17:35:45 -0400
committer AJR <ajrhacker@users.noreply.github.com>2017-03-25 17:35:45 -0400
commit323eb04ded6efbf03ff4355512201a0df0d443a7 (patch)
tree67b13536617fe0ffdfb0b02ecff639e3f8a18f8f /src
parent8ce5aa566f3f8faac454ee875c6495bf475cb6bd (diff)
Memory unit masking and address mirroring fixes (nw)
- Fix a bug which effectively treated AM_MIRROR as AM_SELECT when applied to a single-address range mirrored into a contiguous block. The automatic expansion of zero address masks now only applies to those stemming from (default) configuration, not from optimization. (This allows the assertion in latch8_device to be reinstated.) - Fix a bug where AM_SELECT applied to narrow-width handlers with a submaximal number of subunits would select the wrong address bits or none at all. (This allows rpunch_gga_w to be WRITE8 as intended.) - Add more stringent appropriateness checking of unit masks for narrow-width handlers.
Diffstat (limited to 'src')
-rw-r--r--src/devices/machine/latch8.cpp3
-rw-r--r--src/emu/addrmap.cpp26
-rw-r--r--src/emu/emumem.cpp13
-rw-r--r--src/mame/drivers/rpunch.cpp2
-rw-r--r--src/mame/includes/rpunch.h2
-rw-r--r--src/mame/video/rpunch.cpp5
6 files changed, 36 insertions, 15 deletions
diff --git a/src/devices/machine/latch8.cpp b/src/devices/machine/latch8.cpp
index ca6d2c9f789..3c12ea10129 100644
--- a/src/devices/machine/latch8.cpp
+++ b/src/devices/machine/latch8.cpp
@@ -40,8 +40,7 @@ READ8_MEMBER( latch8_device::read )
{
uint8_t res;
- // FIXME: AM_MIRROR(0xff) doesn't work properly
- //assert(offset == 0);
+ assert(offset == 0);
res = m_value;
if (m_has_read)
diff --git a/src/emu/addrmap.cpp b/src/emu/addrmap.cpp
index 5b12f139026..d6e0290e4f0 100644
--- a/src/emu/addrmap.cpp
+++ b/src/emu/addrmap.cpp
@@ -288,15 +288,39 @@ bool address_map_entry::unitmask_is_appropriate(u8 width, u64 unitmask, const ch
if (m_map.m_databits < width)
throw emu_fatalerror("Handler %s is a %d-bit handler and is too wide to be used in a %d-bit address map", string, width, m_map.m_databits);
+ // if map is narrower than 64 bits, check the mask width as well
+ if (m_map.m_databits < 64 && (unitmask >> m_map.m_databits) != 0)
+ throw emu_fatalerror("Handler %s specified a mask of %08X%08X, too wide to be used in a %d-bit address map", string, (u32)(unitmask >> 32), (u32)unitmask, m_map.m_databits);
+
// the mask must represent whole units of width
u32 basemask = (width == 8) ? 0xff : (width == 16) ? 0xffff : 0xffffffff;
u64 singlemask = basemask;
+ int count = 0;
while (singlemask != 0)
{
- if ((unitmask & singlemask) != 0 && (unitmask & singlemask) != singlemask)
+ if ((unitmask & singlemask) == singlemask)
+ count++;
+ else if ((unitmask & singlemask) != 0)
throw emu_fatalerror("Handler %s specified a mask of %08X%08X; needs to be in even chunks of %X", string, (u32)(unitmask >> 32), (u32)unitmask, basemask);
singlemask <<= width;
}
+
+ // subunit count must be a power of 2
+ if (count != 1 && count != 2 && count != 4 && count != 8)
+ throw emu_fatalerror("Handler %s specifies %d subunits with a mask of %08X%08X; needs to be a power of 2", string, count, (u32)(unitmask >> 32), (u32)unitmask);
+
+ // the mask must be symmetrical
+ u64 unitmask_bh = unitmask >> 8 & 0x00ff00ff00ff00ffU;
+ u64 unitmask_bl = unitmask & 0x00ff00ff00ff00ffU;
+ u64 unitmask_wh = unitmask >> 16 & 0x0000ffff0000ffffU;
+ u64 unitmask_wl = unitmask & 0x0000ffff0000ffffU;
+ u64 unitmask_dh = unitmask >> 32 & 0x00000000ffffffffU;
+ u64 unitmask_dl = unitmask & 0x00000000ffffffffU;
+ if ((unitmask_bh != 0 && unitmask_bl != 0 && unitmask_bh != unitmask_bl)
+ || (unitmask_wh != 0 && unitmask_wl != 0 && unitmask_wh != unitmask_wl)
+ || (unitmask_dh != 0 && unitmask_dl != 0 && unitmask_dh != unitmask_dl))
+ throw emu_fatalerror("Handler %s specified an asymmetrical mask of %08X%08X", string, (u32)(unitmask >> 32), (u32)unitmask);
+
return true;
}
diff --git a/src/emu/emumem.cpp b/src/emu/emumem.cpp
index 723d705914a..432115400ed 100644
--- a/src/emu/emumem.cpp
+++ b/src/emu/emumem.cpp
@@ -1853,10 +1853,7 @@ void address_space::allocate(std::vector<std::unique_ptr<address_space>> &space_
inline void address_space::adjust_addresses(offs_t &start, offs_t &end, offs_t &mask, offs_t &mirror)
{
// adjust start/end/mask values
- if (mask == 0)
- mask = m_addrmask & ~mirror;
- else
- mask &= m_addrmask;
+ mask &= m_addrmask;
start &= ~mirror & m_addrmask;
end &= ~mirror & m_addrmask;
@@ -2027,7 +2024,7 @@ void address_space::prepare_map()
entry.m_bytestart = entry.m_addrstart;
entry.m_byteend = entry.m_addrend;
entry.m_bytemirror = entry.m_addrmirror;
- entry.m_bytemask = entry.m_addrmask;
+ entry.m_bytemask = entry.m_addrmask ? entry.m_addrmask : ~entry.m_addrmirror;
adjust_addresses(entry.m_bytestart, entry.m_byteend, entry.m_bytemask, entry.m_bytemirror);
// if we have a share entry, add it to our map
@@ -2857,7 +2854,7 @@ memory_bank &address_space::bank_find_or_allocate(const char *tag, offs_t addrst
// adjust the addresses, handling mirrors and such
offs_t bytemirror = addrmirror;
offs_t bytestart = addrstart;
- offs_t bytemask = 0;
+ offs_t bytemask = ~addrmirror;
offs_t byteend = addrend;
adjust_addresses(bytestart, byteend, bytemask, bytemirror);
@@ -4380,6 +4377,8 @@ void handler_entry::configure_subunits(u64 handlermask, int handlerbits, int &st
if ((scanmask & unitmask) != 0)
count++;
}
+ assert(count != 0);
+ assert(maxunits % count == 0);
// fill in the shifts
int cur_offset = 0;
@@ -4389,7 +4388,7 @@ void handler_entry::configure_subunits(u64 handlermask, int handlerbits, int &st
u32 shift = (unitnum^shift_xor_mask) * handlerbits;
if (((handlermask >> shift) & unitmask) != 0)
{
- m_subunit_infos[m_subunits].m_bytemask = m_bytemask;
+ m_subunit_infos[m_subunits].m_bytemask = m_bytemask / (maxunits / count);
m_subunit_infos[m_subunits].m_mask = unitmask;
m_subunit_infos[m_subunits].m_offset = cur_offset++;
m_subunit_infos[m_subunits].m_size = handlerbits;
diff --git a/src/mame/drivers/rpunch.cpp b/src/mame/drivers/rpunch.cpp
index 1a4a79320c4..81c7feeb113 100644
--- a/src/mame/drivers/rpunch.cpp
+++ b/src/mame/drivers/rpunch.cpp
@@ -247,7 +247,7 @@ static ADDRESS_MAP_START( main_map, AS_PROGRAM, 16, rpunch_state )
AM_RANGE(0x080000, 0x083fff) AM_RAM_WRITE(rpunch_videoram_w) AM_SHARE("videoram")
AM_RANGE(0x0a0000, 0x0a07ff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
AM_RANGE(0x0c0000, 0x0c0007) AM_WRITE(rpunch_scrollreg_w)
- AM_RANGE(0x0c0008, 0x0c0009) AM_SELECT(0x20) AM_WRITE(rpunch_gga_w)
+ AM_RANGE(0x0c0008, 0x0c0009) AM_SELECT(0x20) AM_WRITE8(rpunch_gga_w, 0x00ff)
AM_RANGE(0x0c000c, 0x0c000d) AM_WRITE(rpunch_videoreg_w)
AM_RANGE(0x0c000e, 0x0c000f) AM_WRITE(sound_command_w)
AM_RANGE(0x0c0010, 0x0c0013) AM_WRITE(rpunch_ins_w)
diff --git a/src/mame/includes/rpunch.h b/src/mame/includes/rpunch.h
index a6c08a36abf..20b88d8887e 100644
--- a/src/mame/includes/rpunch.h
+++ b/src/mame/includes/rpunch.h
@@ -50,7 +50,7 @@ public:
DECLARE_WRITE16_MEMBER(rpunch_videoram_w);
DECLARE_WRITE16_MEMBER(rpunch_videoreg_w);
DECLARE_WRITE16_MEMBER(rpunch_scrollreg_w);
- DECLARE_WRITE16_MEMBER(rpunch_gga_w);
+ DECLARE_WRITE8_MEMBER(rpunch_gga_w);
DECLARE_WRITE8_MEMBER(rpunch_gga_data_w);
DECLARE_WRITE16_MEMBER(rpunch_ins_w);
DECLARE_CUSTOM_INPUT_MEMBER(hi_bits_r);
diff --git a/src/mame/video/rpunch.cpp b/src/mame/video/rpunch.cpp
index 2d24bd59733..b3a072db267 100644
--- a/src/mame/video/rpunch.cpp
+++ b/src/mame/video/rpunch.cpp
@@ -152,10 +152,9 @@ WRITE16_MEMBER(rpunch_state::rpunch_scrollreg_w)
}
-WRITE16_MEMBER(rpunch_state::rpunch_gga_w)
+WRITE8_MEMBER(rpunch_state::rpunch_gga_w)
{
- if (ACCESSING_BITS_0_7)
- m_gga->write(space, offset >> 4, data & 0xff);
+ m_gga->write(space, offset >> 4, data & 0xff);
}