diff options
Diffstat (limited to 'src/emu/addrmap.cpp')
-rw-r--r-- | src/emu/addrmap.cpp | 117 |
1 files changed, 69 insertions, 48 deletions
diff --git a/src/emu/addrmap.cpp b/src/emu/addrmap.cpp index 604e05ab864..81e91457e71 100644 --- a/src/emu/addrmap.cpp +++ b/src/emu/addrmap.cpp @@ -19,39 +19,6 @@ #define DETECT_OVERLAPPING_MEMORY (0) -/*------------------------------------------------- - core_i64_hex_format - i64 format printf helper - why isn't fatalerror going through the same - channels as logerror exactly? --------------------------------------------------*/ - -static char *core_i64_hex_format(u64 value, u8 mindigits) -{ - static char buffer[16][64]; - // TODO: this can overflow - e.g. when a lot of unmapped writes are logged - static int index; - char *bufbase = &buffer[index++ % 16][0]; - char *bufptr = bufbase; - s8 curdigit; - - for (curdigit = 15; curdigit >= 0; curdigit--) - { - int nibble = (value >> (curdigit * 4)) & 0xf; - if (nibble != 0 || curdigit < mindigits) - { - mindigits = curdigit; - *bufptr++ = "0123456789ABCDEF"[nibble]; - } - } - if (bufptr == bufbase) - *bufptr++ = '0'; - *bufptr = 0; - - return bufbase; -} - - - //************************************************************************** // ADDRESS MAP ENTRY //************************************************************************** @@ -71,9 +38,13 @@ address_map_entry::address_map_entry(device_t &device, address_map &map, offs_t , m_addrselect(0) , m_mask(0) , m_cswidth(0) + , m_flags(0) , m_share(nullptr) , m_region(nullptr) , m_rgnoffs(0) + , m_before_time(device) + , m_before_delay(device) + , m_after_delay(device) , m_rproto8(device) , m_rproto16(device) , m_rproto32(device) @@ -201,6 +172,15 @@ address_map_entry &address_map_entry::m(device_t *device, address_map_constructo return *this; } +void address_map_entry::view(memory_view &mv) +{ + m_read.m_type = AMH_VIEW; + m_read.m_tag = nullptr; + m_write.m_type = AMH_VIEW; + m_write.m_tag = nullptr; + m_view = &mv; + mv.initialize_from_address_map(m_addrstart, m_addrend, m_map.get_config()); +} //------------------------------------------------- // r/w/rw - handler setters for @@ -787,6 +767,7 @@ bool address_map_entry::unitmask_is_appropriate(u8 width, u64 unitmask, const ch address_map::address_map(device_t &device, int spacenum) : m_spacenum(spacenum), m_device(&device), + m_view(nullptr), m_unmapval(0), m_globalmask(0) { @@ -796,8 +777,8 @@ address_map::address_map(device_t &device, int spacenum) throw emu_fatalerror("No memory interface defined for device '%s'\n", m_device->tag()); // and then the configuration for the current address space - const address_space_config *spaceconfig = memintf->space_config(spacenum); - if (spaceconfig == nullptr) + m_config = memintf->space_config(spacenum); + if (m_config == nullptr) throw emu_fatalerror("No memory address space configuration found for device '%s', space %d\n", m_device->tag(), spacenum); // append the map provided by the owner @@ -809,8 +790,8 @@ address_map::address_map(device_t &device, int spacenum) } // construct the internal device map (last so it takes priority) - if (!spaceconfig->m_internal_map.isnull()) - spaceconfig->m_internal_map(*this); + if (!m_config->m_internal_map.isnull()) + m_config->m_internal_map(*this); } @@ -822,6 +803,8 @@ address_map::address_map(device_t &device, int spacenum) address_map::address_map(device_t &device, address_map_entry *entry) : m_spacenum(AS_PROGRAM), m_device(&device), + m_view(nullptr), + m_config(entry->m_map.m_config), m_unmapval(0), m_globalmask(0) { @@ -836,13 +819,30 @@ address_map::address_map(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, u64 unitmask, int cswidth, device_t &device, address_map_constructor submap_delegate) +address_map::address_map(const address_space &space, offs_t start, offs_t end, u64 unitmask, int cswidth, u16 flags, device_t &device, address_map_constructor submap_delegate) : m_spacenum(space.spacenum()), m_device(&device), + m_view(nullptr), + m_config(&space.space_config()), m_unmapval(space.unmap()), m_globalmask(space.addrmask()) { - (*this)(start, end).m(DEVICE_SELF, submap_delegate).umask64(unitmask).cswidth(cswidth); + (*this)(start, end).m(DEVICE_SELF, submap_delegate).umask64(unitmask).cswidth(cswidth).flags(flags); +} + + +//---------------------------------------------------------- +// address_map - constructor memory view mapping case +//---------------------------------------------------------- + +address_map::address_map(memory_view &view) + : m_spacenum(-1), + m_device(&view.m_device), + m_view(&view), + m_config(view.m_config), + m_unmapval(0), + m_globalmask(0) +{ } @@ -898,7 +898,7 @@ void address_map::import_submaps(running_machine &machine, device_t &owner, int { mapdevice = owner.subdevice(entry->m_read.m_tag); if (mapdevice == nullptr) - throw emu_fatalerror("Attempted to submap a non-existent device '%s' in space %d of device '%s'\n", owner.subtag(entry->m_read.m_tag).c_str(), m_spacenum, m_device->basetag()); + throw emu_fatalerror("Attempted to submap a non-existent device '%s' in space %d of device '%s'\n", owner.subtag(entry->m_read.m_tag), m_spacenum, m_device->basetag()); } // Grab the submap @@ -981,7 +981,7 @@ void address_map::import_submaps(running_machine &machine, device_t &owner, int subentry_ratio ++; subentry_ratio = data_width / subentry_ratio; if (ratio * subentry_ratio > data_width / 8) - fatalerror("import_submap: In range %x-%x mask %x mirror %x select %x of device %s, the import unitmask of %s combined with an entry unitmask of %s does not fit in %d bits.\n", subentry->m_addrstart, subentry->m_addrend, subentry->m_addrmask, subentry->m_addrmirror, subentry->m_addrselect, entry->m_read.m_tag, core_i64_hex_format(entry->m_mask, data_width/4), core_i64_hex_format(subentry->m_mask, data_width/4), data_width); + fatalerror("import_submap: In range %x-%x mask %x mirror %x select %x of device %s, the import unitmask of %0*x combined with an entry unitmask of %0*x does not fit in %d bits.\n", subentry->m_addrstart, subentry->m_addrend, subentry->m_addrmask, subentry->m_addrmirror, subentry->m_addrselect, entry->m_read.m_tag, data_width/4, entry->m_mask, data_width/4, subentry->m_mask, data_width); // Regenerate the unitmask u64 newmask = 0; @@ -999,6 +999,7 @@ void address_map::import_submaps(running_machine &machine, device_t &owner, int subentry->m_mask = entry->m_mask; subentry->m_cswidth = std::max(subentry->m_cswidth, entry->m_cswidth); + subentry->m_flags = subentry->m_flags | entry->m_flags; if (subentry->m_addrend > max_end) subentry->m_addrend = max_end; @@ -1148,25 +1149,40 @@ void address_map::map_validity_check(validity_checker &valid, int spacenum) cons osd_printf_error("In %s memory range %x-%x, mirror %x touches a select bit (%x)\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend, entry.m_addrmirror, entry.m_addrmirror & entry.m_addrselect); // if this is a program space, auto-assign implicit ROM entries - if (entry.m_read.m_type == AMH_ROM && entry.m_region == nullptr) + if (entry.m_read.m_type == AMH_ROM && entry.m_region == nullptr && spacenum == AS_PROGRAM && entry.m_share == nullptr) { entry.m_region = m_device->tag(); entry.m_rgnoffs = entry.m_addrstart; } + // detect conflicts between region and share + if (entry.m_region && entry.m_share) + osd_printf_error("%s space memory map entry %X-%X has both .region() and .share()\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend); + + + // Detect inaccesible memory. Region automapping is handled before + if (entry.m_read.m_type == AMH_ROM && entry.m_write.m_type != AMH_RAM && + !entry.m_share && !entry.m_region) + osd_printf_error("%s space memory map entry %X-%X has .rom() but no .region() or .share()\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend); + if (entry.m_read.m_type != AMH_RAM && entry.m_write.m_type == AMH_RAM && + !entry.m_share) + osd_printf_error("%s space memory map entry %X-%X has .writeonly() but no .share()\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend); + // if this entry references a memory region, validate it - if (entry.m_region != nullptr && entry.m_share == nullptr) + if (entry.m_region != nullptr) { // address map entries that reference regions but are NOPs are pointless - if (entry.m_read.m_type == AMH_NONE && entry.m_write.m_type == AMH_NONE) - osd_printf_error("%s space references memory region %s, but is noprw()\n", spaceconfig.m_name, entry.m_region); + if (entry.m_read.m_type != AMH_ROM && entry.m_read.m_type != AMH_RAM) + osd_printf_error("%s space memory map entry %X-%X references memory region %s, but can't read it\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend, entry.m_region); + if (entry.m_write.m_type == AMH_RAM) + osd_printf_error("%s space memory map entry %X-%X references memory region %s, but wants to write to it\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend, entry.m_region); // make sure we can resolve the full path to the region bool found = false; std::string entry_region = entry.m_devbase.subtag(entry.m_region); // look for the region - for (device_t &dev : device_iterator(m_device->mconfig().root_device())) + for (device_t &dev : device_enumerator(m_device->mconfig().root_device())) { for (romload::region const ®ion : romload::entries(dev.rom_region()).get_regions()) { @@ -1287,7 +1303,7 @@ void address_map::map_validity_check(validity_checker &valid, int spacenum) cons break; } if (devtag.second && !devtag.first.get().subdevice(devtag.second)) - osd_printf_error("%s space memory map entry reads from nonexistent device '%s'\n", spaceconfig.m_name, devtag.first.get().subtag(devtag.second).c_str()); + osd_printf_error("%s space memory map entry reads from nonexistent device '%s'\n", spaceconfig.m_name, devtag.first.get().subtag(devtag.second)); #ifndef MAME_DEBUG // assert will catch this earlier (void)entry.unitmask_is_appropriate(entry.m_read.m_bits, entry.m_mask, entry.m_read.m_name); #endif @@ -1359,7 +1375,7 @@ void address_map::map_validity_check(validity_checker &valid, int spacenum) cons break; } if (devtag.second && !devtag.first.get().subdevice(devtag.second)) - osd_printf_error("%s space memory map entry writes to nonexistent device '%s'\n", spaceconfig.m_name, devtag.first.get().subtag(devtag.second).c_str()); + osd_printf_error("%s space memory map entry writes to nonexistent device '%s'\n", spaceconfig.m_name, devtag.first.get().subtag(devtag.second)); #ifndef MAME_DEBUG // assert will catch this earlier (void)entry.unitmask_is_appropriate(entry.m_write.m_bits, entry.m_mask, entry.m_write.m_name); #endif @@ -1379,3 +1395,8 @@ void address_map::map_validity_check(validity_checker &valid, int spacenum) cons valid.validate_tag(entry.m_share); } } + +const address_space_config &address_map::get_config() const +{ + return *m_config; +} |