inline void map_handler_data::set_tag(const device_t &device, const char *tag) { if (strcmp(tag, DEVICE_SELF) == 0) m_tag = device.tag(); else if (strcmp(tag, DEVICE_SELF_OWNER) == 0) { assert(device.owner() != NULL); m_tag = device.owner()->tag(); } else m_tag = device.subtag(m_derived_tag, tag); }
void load_software_part_region(device_t &device, software_list_device &swlist, const char *swname, const rom_entry *start_region) { astring locationtag(swlist.list_name()), breakstr("%"); romload_private *romdata = device.machine().romload_data; const rom_entry *region; astring regiontag; romdata->errorstring.reset(); romdata->softwarningstring.reset(); romdata->romstotal = 0; romdata->romstotalsize = 0; romdata->romsloadedsize = 0; software_info *swinfo = swlist.find(swname); if (swinfo != NULL) { UINT32 supported = swinfo->supported(); if (supported == SOFTWARE_SUPPORTED_PARTIAL) { romdata->errorstring.catprintf("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist.list_name()); romdata->softwarningstring.catprintf("Support for software %s (in list %s) is only partial\n", swname, swlist.list_name()); } if (supported == SOFTWARE_SUPPORTED_NO) { romdata->errorstring.catprintf("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist.list_name()); romdata->softwarningstring.catprintf("Support for software %s (in list %s) is only preliminary\n", swname, swlist.list_name()); } // attempt reading up the chain through the parents and create a locationtag astring in the format // " swlist % clonename % parentname " // open_rom_file contains the code to split the elements and to create paths to load from locationtag.cat(breakstr); while (swinfo != NULL) { locationtag.cat(swinfo->shortname()).cat(breakstr); const char *parentname = swinfo->parentname(); swinfo = (parentname != NULL) ? swlist.find(parentname) : NULL; } // strip the final '%' locationtag.del(locationtag.len() - 1, 1); } /* loop until we hit the end */ for (region = start_region; region != NULL; region = rom_next_region(region)) { UINT32 regionlength = ROMREGION_GETLENGTH(region); device.subtag(regiontag, ROMREGION_GETTAG(region)); LOG(("Processing region \"%s\" (length=%X)\n", regiontag.cstr(), regionlength)); /* the first entry must be a region */ assert(ROMENTRY_ISREGION(region)); /* if this is a device region, override with the device width and endianness */ endianness_t endianness = ROMREGION_ISBIGENDIAN(region) ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; UINT8 width = ROMREGION_GETWIDTH(region) / 8; memory_region *memregion = romdata->machine().root_device().memregion(regiontag); if (memregion != NULL) { if (romdata->machine().device(regiontag) != NULL) normalize_flags_for_device(romdata->machine(), regiontag, width, endianness); /* clear old region (todo: should be moved to an image unload function) */ romdata->machine().memory().region_free(memregion->name()); } /* remember the base and length */ romdata->region = romdata->machine().memory().region_alloc(regiontag, regionlength, width, endianness); LOG(("Allocated %X bytes @ %p\n", romdata->region->bytes(), romdata->region->base())); /* clear the region if it's requested */ if (ROMREGION_ISERASE(region)) memset(romdata->region->base(), ROMREGION_GETERASEVAL(region), romdata->region->bytes()); /* or if it's sufficiently small (<= 4MB) */ else if (romdata->region->bytes() <= 0x400000) memset(romdata->region->base(), 0, romdata->region->bytes()); #ifdef MAME_DEBUG /* if we're debugging, fill region with random data to catch errors */ else fill_random(romdata->machine(), romdata->region->base(), romdata->region->bytes()); #endif /* update total number of roms */ for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) { romdata->romstotal++; romdata->romstotalsize += rom_file_size(rom); } /* now process the entries in the region */ if (ROMREGION_ISROMDATA(region)) process_rom_entries(romdata, locationtag, region, region + 1, &device, TRUE); else if (ROMREGION_ISDISKDATA(region)) process_disk_entries(romdata, core_strdup(regiontag.cstr()), region, region + 1, locationtag); } /* now go back and post-process all the regions */ for (region = start_region; region != NULL; region = rom_next_region(region)) { device.subtag(regiontag, ROMREGION_GETTAG(region)); region_post_process(romdata, regiontag.cstr(), ROMREGION_ISINVERTED(region)); } /* display the results and exit */ display_rom_load_results(romdata, TRUE); }
std::string rom_parameter_name(const device_t &device, const rom_entry *romp) { return device.subtag(romp->_name); }
std::string rom_region_name(const device_t &device, const rom_entry *romp) { return device.subtag(ROM_GETNAME(romp)); }
void address_map::uplift_submaps(running_machine &machine, device_t &device, device_t &owner, endianness_t endian) { address_map_entry *prev = 0; address_map_entry *entry = m_entrylist.first(); while (entry) { if (entry->m_read.m_type == AMH_DEVICE_SUBMAP) { std::string tag = owner.subtag(entry->m_read.m_tag); device_t *mapdevice = machine.device(tag.c_str()); if (mapdevice == NULL) { throw emu_fatalerror("Attempted to submap a non-existent device '%s' in space %d of device '%s'\n", tag.c_str(), m_spacenum, device.basetag()); } // Grab the submap address_map submap(*mapdevice, entry); // Recursively uplift it if needed submap.uplift_submaps(machine, device, *mapdevice, endian); // Compute the unit repartition characteristics int entry_bits = entry->m_submap_bits; if (!entry_bits) entry_bits = m_databits; if (submap.m_databits != entry_bits) throw emu_fatalerror("AM_DEVICE wants a %d bits large address map and got a %d bits large one instead.\n", entry_bits, submap.m_databits); int entry_bytes = entry_bits / 8; int databytes = m_databits / 8; offs_t mirror_address_mask = (databytes - 1) & ~(entry_bytes - 1); UINT64 entry_mask = (2ULL << (entry_bits-1)) - 1; int slot_offset[8]; int slot_count = 0; int max_slot_count = m_databits / entry_bits; int slot_xor_mask = endian == ENDIANNESS_LITTLE ? 0 : max_slot_count - 1; UINT64 global_mask = entry->m_read.m_mask; // zero means all if (!global_mask) global_mask = ~global_mask; // mask consistency has already been checked in // unitmask_is_appropriate, so one bit is enough for (int slot=0; slot < max_slot_count; slot++) if (global_mask & (1ULL << ((slot ^ slot_xor_mask) * entry_bits))) slot_offset[slot_count++] = (slot ^ slot_xor_mask) * entry_bits; // Merge in all the map contents in order while (submap.m_entrylist.count()) { address_map_entry *subentry = submap.m_entrylist.detach_head(); // Remap start and end unsigned int start_offset = subentry->m_addrstart / entry_bytes; unsigned int start_slot = start_offset % slot_count; subentry->m_addrstart = entry->m_addrstart + (start_offset / slot_count) * databytes; // Drop the entry if it ends up outside the range if (subentry->m_addrstart > entry->m_addrend) { global_free(subentry); continue; } unsigned int end_offset = subentry->m_addrend / entry_bytes; unsigned int end_slot = end_offset % slot_count; subentry->m_addrend = entry->m_addrstart + (end_offset / slot_count) * databytes + databytes - 1; // Clip the entry to the end of the range if (subentry->m_addrend > entry->m_addrend || subentry->m_addrend < entry->m_addrstart) subentry->m_addrend = entry->m_addrend; // Detect special unhandled case (range straddling // slots, requiring splitting in multiple entries and // unimplemented offset-add subunit handler) if (subentry->m_addrstart + databytes - 1 != subentry->m_addrend && (start_slot != 0 || end_slot != slot_count - 1)) throw emu_fatalerror("uplift_submaps unhandled case: range straddling slots.\n"); if (entry->m_addrmask || subentry->m_addrmask) throw emu_fatalerror("uplift_submaps unhandled case: address masks.\n"); if (subentry->m_addrmirror & mirror_address_mask) throw emu_fatalerror("uplift_submaps unhandled case: address mirror bit within subentry.\n"); subentry->m_addrmirror |= entry->m_addrmirror; // Twiddle the unitmask on the data accessors that need it for (int data_entry = 0; data_entry < 3; data_entry++) { map_handler_data &mdata = (data_entry==0)? subentry->m_read : ((data_entry==1)? subentry->m_write : subentry->m_setoffsethd); if (mdata.m_type == AMH_NONE) continue; if (mdata.m_type != AMH_DEVICE_DELEGATE && mdata.m_type != AMH_NOP) throw emu_fatalerror("Only normal read/write methods are accepted in device submaps.\n"); if (mdata.m_bits == 0 && entry_bits != m_databits) mdata.m_bits = entry_bits; UINT64 mask = 0; if (mdata.m_bits != m_databits) { UINT64 unitmask = mdata.m_mask ? mdata.m_mask : entry_mask; for (int slot = start_slot; slot <= end_slot; slot++) mask |= unitmask << slot_offset[slot]; } mdata.m_mask = mask; } // Insert the entry in the map m_entrylist.insert_after(*subentry, prev); prev = subentry; } address_map_entry *to_delete = entry; entry = entry->next(); m_entrylist.remove(*to_delete); } else { prev = entry; entry = entry->next(); } } }