mirror of
https://github.com/holub/mame
synced 2025-10-05 08:41:31 +03:00
memory: Implement depopulate_unused(). [O. Galibert]
depopulate_unused is essentially the garbage collector for bottom-level handlers. The previous code was working around not having it implemented yet by reusing handlers with the same start address, end address and address mask. The problem with that trick is that it is slightly incorrect. If you have a memory map with: AM_RANGE(0x0000, 0x0fff) AM_READ(up_r) AM_RANGE(0x0000, 0x0fff) AM_READ(down_r) AM_MIRROR(0x8000) then the range 8000..8fff would have called up_r instead of down_r due to the handler reuse. The mirror value is not saved, hence not compared. New code doesn't use the trick, so doesn't call the wrong handler, but OTOH eats handlers for breakfast. It's important to note that such a memory map is so highly improbable hardware-wise that it wasn't worth worrying about. But it's a behaviour change it is interesting to keep in mind. In particular since the up_r range can be added through an install_read_handler instead of a static map.
This commit is contained in:
parent
d5370bdafb
commit
459102e95f
@ -475,6 +475,13 @@ public:
|
||||
// reconfigure the subunits on a base address change
|
||||
void reconfigure_subunits(offs_t bytestart);
|
||||
|
||||
// depopulate an handler
|
||||
void deconfigure()
|
||||
{
|
||||
m_populated = false;
|
||||
m_subunits = 0;
|
||||
}
|
||||
|
||||
// apply a global mask
|
||||
void apply_mask(offs_t bytemask) { m_bytemask &= bytemask; }
|
||||
|
||||
@ -3543,7 +3550,31 @@ void address_table::populate_range_mirrored(offs_t bytestart, offs_t byteend, of
|
||||
|
||||
void address_table::depopulate_unused()
|
||||
{
|
||||
assert(false);
|
||||
bool used[SUBTABLE_BASE - STATIC_COUNT];
|
||||
memset(used, 0, sizeof(used));
|
||||
|
||||
for (int level1 = 0; level1 != 1 << LEVEL1_BITS; level1++)
|
||||
{
|
||||
UINT8 l1_entry = m_table[level1];
|
||||
if (l1_entry >= SUBTABLE_BASE)
|
||||
{
|
||||
assert(m_large);
|
||||
const UINT8 *subtable = subtable_ptr(l1_entry);
|
||||
for (int level2 = 0; level2 != 1 << LEVEL2_BITS; level2++)
|
||||
{
|
||||
UINT8 l2_entry = subtable[level2];
|
||||
assert(l2_entry < SUBTABLE_BASE);
|
||||
if (l2_entry >= STATIC_COUNT)
|
||||
used[l2_entry - STATIC_COUNT] = true;
|
||||
}
|
||||
}
|
||||
else if (l1_entry >= STATIC_COUNT)
|
||||
used[l1_entry - STATIC_COUNT] = true;
|
||||
}
|
||||
|
||||
for (int slot=0; slot != SUBTABLE_BASE - STATIC_COUNT; slot++)
|
||||
if (!used[slot])
|
||||
handler(slot + STATIC_COUNT).deconfigure();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user