From 40c79602b62b298629e19d119013497c3d4d1a80 Mon Sep 17 00:00:00 2001 From: Olivier Galibert Date: Fri, 3 Aug 2012 18:55:37 +0000 Subject: [PATCH] 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); --- src/emu/addrmap.c | 32 ++++++++++++++++++++++++++++++++ src/emu/addrmap.h | 4 +--- src/emu/memory.c | 26 ++++++++++++++++++++++---- src/emu/memory.h | 13 ++++++++++++- 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/src/emu/addrmap.c b/src/emu/addrmap.c index 631bf544267..76a43a84be9 100644 --- a/src/emu/addrmap.c +++ b/src/emu/addrmap.c @@ -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 //------------------------------------------------- diff --git a/src/emu/addrmap.h b/src/emu/addrmap.h index a597f540b8a..08e181c3e1e 100644 --- a/src/emu/addrmap.h +++ b/src/emu/addrmap.h @@ -74,9 +74,6 @@ enum map_handler_type // TYPE DEFINITIONS //************************************************************************** -// submap retriever delegate -typedef delegate 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 diff --git a/src/emu/memory.c b/src/emu/memory.c index fc9f48ea49c..80eb916159d 100644 --- a/src/emu/memory.c +++ b/src/emu/memory.c @@ -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 diff --git a/src/emu/memory.h b/src/emu/memory.h index 20b9801f3aa..cb3f75f6561 100644 --- a/src/emu/memory.h +++ b/src/emu/memory.h @@ -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 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 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();