memory: Add support for dynamically mapping devices [O. Galibert]

Just call install_device on the space with as parameters:
- start and end of the mapping zone
- device (not pointer to the device)
- map method

and optionally, if the device data width is not the same than the
space data width:
- device data width (for consistency checking)
- unit mask

For instance, the static mapping:
  AM_RANGE(0x02114100, 0x02114107) AM_DEVICE8("fdc", n82077aa_device, amap, 0xffffffff)

can be converted to a dynamic mapping (where fdc is a pointer to the device):
  machine().device("maincpu")->memory().space(AS_PROGRAM)->
    install_device(0x02114100, 0x02114107, *fdc, &n82077aa_device::amap, 8, 0xffffffff);
This commit is contained in:
Olivier Galibert 2012-08-03 18:55:37 +00:00
parent bf013678a7
commit 40c79602b6
4 changed files with 67 additions and 8 deletions

View File

@ -739,6 +739,38 @@ address_map::address_map(const device_t &device, address_map_entry *entry)
}
//----------------------------------------------------------
// address_map - constructor dynamic device mapping case
//----------------------------------------------------------
address_map::address_map(const address_space &space, offs_t start, offs_t end, int bits, UINT64 unitmask, const device_t &device, address_map_delegate submap_delegate)
: m_spacenum(space.spacenum()),
m_databits(space.data_width()),
m_unmapval(space.unmap()),
m_globalmask(space.bytemask())
{
address_map_entry *e;
switch(m_databits) {
case 8:
e = add(start, end, (address_map_entry8 *)NULL);
break;
case 16:
e = add(start, end, (address_map_entry16 *)NULL);
break;
case 32:
e = add(start, end, (address_map_entry32 *)NULL);
break;
case 64:
e = add(start, end, (address_map_entry64 *)NULL);
break;
default:
throw emu_fatalerror("Trying to dynamically map a device on a space with a corrupt databits width");
}
e->set_submap(device, DEVICE_SELF, submap_delegate, bits, unitmask);
}
//-------------------------------------------------
// ~address_map - destructor
//-------------------------------------------------

View File

@ -74,9 +74,6 @@ enum map_handler_type
// TYPE DEFINITIONS
//**************************************************************************
// submap retriever delegate
typedef delegate<void (address_map &, const device_t &)> address_map_delegate;
// address map handler data
class map_handler_data
{
@ -411,6 +408,7 @@ public:
// construction/destruction
address_map(const device_t &device, address_spacenum spacenum);
address_map(const device_t &device, address_map_entry *entry);
address_map(const address_space &space, offs_t start, offs_t end, int bits, UINT64 unitmask, const device_t &device, address_map_delegate submap_delegate);
~address_map();
// configuration

View File

@ -1894,19 +1894,23 @@ void address_space::prepare_map()
// each case
//-------------------------------------------------
void address_space::populate_from_map()
void address_space::populate_from_map(address_map *map)
{
// no map specified, use the space-specific one
if (map == NULL)
map = m_map;
// no map, nothing to do
if (m_map == NULL)
if (map == NULL)
return;
// install the handlers, using the original, unadjusted memory map
const address_map_entry *last_entry = NULL;
while (last_entry != m_map->m_entrylist.first())
while (last_entry != map->m_entrylist.first())
{
// find the entry before the last one we processed
const address_map_entry *entry;
for (entry = m_map->m_entrylist.first(); entry->next() != last_entry; entry = entry->next()) ;
for (entry = map->m_entrylist.first(); entry->next() != last_entry; entry = entry->next()) ;
last_entry = entry;
// map both read and write halves
@ -2306,6 +2310,20 @@ void address_space::unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrm
}
//-------------------------------------------------
// install_device_delegate - install the memory map
// of a live device into this address space
//-------------------------------------------------
void address_space::install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_delegate &delegate, int bits, UINT64 unitmask)
{
address_map map(*this, addrstart, addrend, bits, unitmask, device, delegate);
map.uplift_submaps(machine(), m_device, endianness());
populate_from_map(&map);
}
//-------------------------------------------------
// install_readwrite_port - install a new I/O port
// handler into this address space

View File

@ -107,6 +107,9 @@ typedef UINT32 offs_t;
// address map constructors are functions that build up an address_map
typedef void (*address_map_constructor)(address_map &map, const device_t &devconfig);
// submap retriever delegate
typedef delegate<void (address_map &, const device_t &)> address_map_delegate;
// legacy space read/write handlers
typedef UINT8 (*read8_space_func) (ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset);
@ -433,6 +436,14 @@ public:
void *install_writeonly(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, void *baseptr = NULL) { return install_ram_generic(addrstart, addrend, addrmask, addrmirror, ROW_WRITE, baseptr); }
void *install_ram(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, void *baseptr = NULL) { return install_ram_generic(addrstart, addrend, addrmask, addrmirror, ROW_READWRITE, baseptr); }
// install device memory maps
template <typename T> void install_device(offs_t addrstart, offs_t addrend, T &device, void (T::*map)(address_map &map, const device_t &device), int bits = 0, UINT64 unitmask = 0) {
address_map_delegate delegate(map, "dynamic_device_install", &device);
install_device_delegate(addrstart, addrend, device, delegate, bits, unitmask);
}
void install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_delegate &map, int bits = 0, UINT64 unitmask = 0);
// install new-style delegate handlers (short form)
UINT8 *install_read_handler(offs_t addrstart, offs_t addrend, read8_delegate rhandler, UINT64 unitmask = 0) { return install_read_handler(addrstart, addrend, 0, 0, rhandler, unitmask); }
UINT8 *install_write_handler(offs_t addrstart, offs_t addrend, write8_delegate whandler, UINT64 unitmask = 0) { return install_write_handler(addrstart, addrend, 0, 0, whandler, unitmask); }
@ -519,7 +530,7 @@ public:
// setup
void prepare_map();
void populate_from_map();
void populate_from_map(address_map *map = NULL);
void allocate_memory();
void locate_memory();