static void process_region_list(romload_private *romdata) { astring regiontag; /* loop until we hit the end */ device_iterator deviter(romdata->machine().root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) for (const rom_entry *region = rom_first_region(*device); region != NULL; region = rom_next_region(region)) { UINT32 regionlength = ROMREGION_GETLENGTH(region); rom_region_name(regiontag, *device, region); LOG(("Processing region \"%s\" (length=%X)\n", regiontag.cstr(), regionlength)); /* the first entry must be a region */ assert(ROMENTRY_ISREGION(region)); if (ROMREGION_ISROMDATA(region)) { /* if this is a device region, override with the device width and endianness */ UINT8 width = ROMREGION_GETWIDTH(region) / 8; endianness_t endianness = ROMREGION_ISBIGENDIAN(region) ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; if (romdata->machine().device(regiontag) != NULL) normalize_flags_for_device(romdata->machine(), regiontag, width, endianness); /* 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 /* now process the entries in the region */ process_rom_entries(romdata, device->shortname(), region, region + 1, device, FALSE); } else if (ROMREGION_ISDISKDATA(region)) process_disk_entries(romdata, regiontag, region, region + 1, NULL); } /* now go back and post-process all the regions */ for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) for (const rom_entry *region = rom_first_region(*device); region != NULL; region = rom_next_region(region)) { rom_region_name(regiontag, *device, region); region_post_process(romdata, regiontag, ROMREGION_ISINVERTED(region)); } }
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); }
void device_memory_interface::interface_validity_check(validity_checker &valid) const { bool detected_overlap = DETECT_OVERLAPPING_MEMORY ? false : true; // loop over all address spaces for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; spacenum++) { const address_space_config *spaceconfig = space_config(spacenum); if (spaceconfig != NULL) { int datawidth = spaceconfig->m_databus_width; int alignunit = datawidth / 8; // construct the maps ::address_map *map = global_alloc(::address_map(const_cast<device_t &>(device()), spacenum)); // if this is an empty map, just skip it if (map->m_entrylist.first() == NULL) { global_free(map); continue; } // validate the global map parameters if (map->m_spacenum != spacenum) osd_printf_error("Space %d has address space %d handlers!\n", spacenum, map->m_spacenum); if (map->m_databits != datawidth) osd_printf_error("Wrong memory handlers provided for %s space! (width = %d, memory = %08x)\n", spaceconfig->m_name, datawidth, map->m_databits); // loop over entries and look for errors for (address_map_entry *entry = map->m_entrylist.first(); entry != NULL; entry = entry->next()) { UINT32 bytestart = spaceconfig->addr2byte(entry->m_addrstart); UINT32 byteend = spaceconfig->addr2byte_end(entry->m_addrend); // look for overlapping entries if (!detected_overlap) { address_map_entry *scan; for (scan = map->m_entrylist.first(); scan != entry; scan = scan->next()) if (entry->m_addrstart <= scan->m_addrend && entry->m_addrend >= scan->m_addrstart && ((entry->m_read.m_type != AMH_NONE && scan->m_read.m_type != AMH_NONE) || (entry->m_write.m_type != AMH_NONE && scan->m_write.m_type != AMH_NONE))) { osd_printf_warning("%s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_read.m_type, entry->m_write.m_type, scan->m_addrstart, scan->m_addrend, scan->m_read.m_type, scan->m_write.m_type); detected_overlap = true; break; } } // look for inverted start/end pairs if (byteend < bytestart) osd_printf_error("Wrong %s memory read handler start = %08x > end = %08x\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend); // look for misaligned entries if ((bytestart & (alignunit - 1)) != 0 || (byteend & (alignunit - 1)) != (alignunit - 1)) osd_printf_error("Wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, alignunit); // if this is a program space, auto-assign implicit ROM entries if (entry->m_read.m_type == AMH_ROM && entry->m_region == NULL) { entry->m_region = device().tag(); entry->m_rgnoffs = entry->m_addrstart; } // if this entry references a memory region, validate it if (entry->m_region != NULL && entry->m_share == 0) { // make sure we can resolve the full path to the region bool found = false; astring entry_region; entry->m_devbase.subtag(entry_region, entry->m_region); // look for the region device_iterator deviter(device().mconfig().root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) for (const rom_entry *romp = rom_first_region(*device); romp != NULL && !found; romp = rom_next_region(romp)) { astring fulltag; rom_region_name(fulltag, *device, romp); if (fulltag == entry_region) { // verify the address range is within the region's bounds offs_t length = ROMREGION_GETLENGTH(romp); if (entry->m_rgnoffs + (byteend - bytestart + 1) > length) osd_printf_error("%s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region, length); found = true; } } // error if not found if (!found) osd_printf_error("%s space memory map entry %X-%X references non-existant region '%s'\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region); } // make sure all devices exist // FIXME: This doesn't work! AMH_DEVICE_DELEGATE entries don't even set m_tag, the device tag is inside the proto-delegate if (entry->m_read.m_type == AMH_DEVICE_DELEGATE && entry->m_read.m_tag != NULL) { astring temp(entry->m_read.m_tag); if (device().siblingdevice(temp) == NULL) osd_printf_error("%s space memory map entry references nonexistant device '%s'\n", spaceconfig->m_name, entry->m_read.m_tag); } if (entry->m_write.m_type == AMH_DEVICE_DELEGATE && entry->m_write.m_tag != NULL) { astring temp(entry->m_write.m_tag); if (device().siblingdevice(temp) == NULL) osd_printf_error("%s space memory map entry references nonexistant device '%s'\n", spaceconfig->m_name, entry->m_write.m_tag); } // make sure ports exist // if ((entry->m_read.m_type == AMH_PORT && entry->m_read.m_tag != NULL && portlist.find(entry->m_read.m_tag) == NULL) || // (entry->m_write.m_type == AMH_PORT && entry->m_write.m_tag != NULL && portlist.find(entry->m_write.m_tag) == NULL)) // osd_printf_error("%s space memory map entry references nonexistant port tag '%s'\n", spaceconfig->m_name, entry->m_read.m_tag); // validate bank and share tags if (entry->m_read.m_type == AMH_BANK) valid.validate_tag(entry->m_read.m_tag); if (entry->m_write.m_type == AMH_BANK) valid.validate_tag(entry->m_write.m_tag); if (entry->m_share != NULL) valid.validate_tag(entry->m_share); } // release the address map global_free(map); } } }
void rom_load_manager::process_region_list() { std::string regiontag; /* loop until we hit the end */ device_iterator deviter(machine().root_device()); for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) for (const rom_entry *region = rom_first_region(*device); region != nullptr; region = rom_next_region(region)) { UINT32 regionlength = ROMREGION_GETLENGTH(region); regiontag = rom_region_name(*device, region); LOG(("Processing region \"%s\" (length=%X)\n", regiontag.c_str(), regionlength)); /* the first entry must be a region */ assert(ROMENTRY_ISREGION(region)); if (ROMREGION_ISROMDATA(region)) { /* if this is a device region, override with the device width and endianness */ UINT8 width = ROMREGION_GETWIDTH(region) / 8; endianness_t endianness = ROMREGION_ISBIGENDIAN(region) ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; if (machine().device(regiontag.c_str()) != nullptr) normalize_flags_for_device(machine(), regiontag.c_str(), width, endianness); /* remember the base and length */ m_region = machine().memory().region_alloc(regiontag.c_str(), regionlength, width, endianness); LOG(("Allocated %X bytes @ %p\n", m_region->bytes(), m_region->base())); /* clear the region if it's requested */ if (ROMREGION_ISERASE(region)) memset(m_region->base(), ROMREGION_GETERASEVAL(region), m_region->bytes()); /* or if it's sufficiently small (<= 4MB) */ else if (m_region->bytes() <= 0x400000) memset(m_region->base(), 0, m_region->bytes()); #ifdef MAME_DEBUG /* if we're debugging, fill region with random data to catch errors */ else fill_random(m_region->base(), m_region->bytes()); #endif /* now process the entries in the region */ process_rom_entries(device->shortname().c_str(), region, region + 1, device, FALSE); } else if (ROMREGION_ISDISKDATA(region)) process_disk_entries(regiontag.c_str(), region, region + 1, nullptr); } /* now go back and post-process all the regions */ for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) for (const rom_entry *region = rom_first_region(*device); region != nullptr; region = rom_next_region(region)) { regiontag = rom_region_name(*device, region); region_post_process(regiontag.c_str(), ROMREGION_ISINVERTED(region)); } /* and finally register all per-game parameters */ for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) for (const rom_entry *param = rom_first_parameter(*device); param != nullptr; param = rom_next_parameter(param)) { regiontag = rom_parameter_name(*device, param); machine().parameters().add(regiontag, rom_parameter_value(param)); } }
bool device_memory_interface::interface_validity_check(emu_options &options, const game_driver &driver) const { bool detected_overlap = DETECT_OVERLAPPING_MEMORY ? false : true; bool error = false; // loop over all address spaces for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; spacenum++) { const address_space_config *spaceconfig = space_config(spacenum); if (spaceconfig != NULL) { int datawidth = spaceconfig->m_databus_width; int alignunit = datawidth / 8; // construct the maps ::address_map *map = global_alloc(::address_map(device(), spacenum)); // if this is an empty map, just skip it if (map->m_entrylist.first() == NULL) { global_free(map); continue; } // validate the global map parameters if (map->m_spacenum != spacenum) { mame_printf_error("%s: %s device '%s' space %d has address space %d handlers!\n", driver.source_file, driver.name, device().tag(), spacenum, map->m_spacenum); error = true; } if (map->m_databits != datawidth) { mame_printf_error("%s: %s device '%s' uses wrong memory handlers for %s space! (width = %d, memory = %08x)\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, datawidth, map->m_databits); error = true; } // loop over entries and look for errors for (address_map_entry *entry = map->m_entrylist.first(); entry != NULL; entry = entry->next()) { UINT32 bytestart = spaceconfig->addr2byte(entry->m_addrstart); UINT32 byteend = spaceconfig->addr2byte_end(entry->m_addrend); // look for overlapping entries if (!detected_overlap) { address_map_entry *scan; for (scan = map->m_entrylist.first(); scan != entry; scan = scan->next()) if (entry->m_addrstart <= scan->m_addrend && entry->m_addrend >= scan->m_addrstart && ((entry->m_read.m_type != AMH_NONE && scan->m_read.m_type != AMH_NONE) || (entry->m_write.m_type != AMH_NONE && scan->m_write.m_type != AMH_NONE))) { mame_printf_warning("%s: %s '%s' %s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_read.m_type, entry->m_write.m_type, scan->m_addrstart, scan->m_addrend, scan->m_read.m_type, scan->m_write.m_type); detected_overlap = true; break; } } // look for inverted start/end pairs if (byteend < bytestart) { mame_printf_error("%s: %s wrong %s memory read handler start = %08x > end = %08x\n", driver.source_file, driver.name, spaceconfig->m_name, entry->m_addrstart, entry->m_addrend); error = true; } // look for misaligned entries if ((bytestart & (alignunit - 1)) != 0 || (byteend & (alignunit - 1)) != (alignunit - 1)) { mame_printf_error("%s: %s wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", driver.source_file, driver.name, spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, alignunit); error = true; } // if this is a program space, auto-assign implicit ROM entries if (entry->m_read.m_type == AMH_ROM && entry->m_region == NULL) { entry->m_region = device().tag(); entry->m_rgnoffs = entry->m_addrstart; } // if this entry references a memory region, validate it if (entry->m_region != NULL && entry->m_share == 0) { // look for the region bool found = false; for (const rom_source *source = rom_first_source(device().mconfig()); source != NULL && !found; source = rom_next_source(*source)) for (const rom_entry *romp = rom_first_region(*source); !ROMENTRY_ISEND(romp) && !found; romp++) { const char *regiontag_c = ROMREGION_GETTAG(romp); if (regiontag_c != NULL) { astring fulltag; astring regiontag; // a leading : on a region name indicates an absolute region, so fix up accordingly if (entry->m_region[0] == ':') { regiontag = &entry->m_region[1]; } else { if (strchr(entry->m_region,':')) { regiontag = entry->m_region; } else { device().siblingtag(regiontag, entry->m_region); } } rom_region_name(fulltag, &driver, source, romp); if (fulltag.cmp(regiontag) == 0) { // verify the address range is within the region's bounds offs_t length = ROMREGION_GETLENGTH(romp); if (entry->m_rgnoffs + (byteend - bytestart + 1) > length) { mame_printf_error("%s: %s device '%s' %s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region, length); error = true; } found = true; } } } // error if not found if (!found) { mame_printf_error("%s: %s device '%s' %s space memory map entry %X-%X references non-existant region '%s'\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region); error = true; } } // make sure all devices exist if ((entry->m_read.m_type == AMH_LEGACY_DEVICE_HANDLER && entry->m_read.m_tag != NULL && device().mconfig().devicelist().find(entry->m_read.m_tag) == NULL) || (entry->m_write.m_type == AMH_LEGACY_DEVICE_HANDLER && entry->m_write.m_tag != NULL && device().mconfig().devicelist().find(entry->m_write.m_tag) == NULL)) { mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant device '%s'\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_write.m_tag); error = true; } // make sure ports exist // if ((entry->m_read.m_type == AMH_PORT && entry->m_read.m_tag != NULL && portlist.find(entry->m_read.m_tag) == NULL) || // (entry->m_write.m_type == AMH_PORT && entry->m_write.m_tag != NULL && portlist.find(entry->m_write.m_tag) == NULL)) // { // mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant port tag '%s'\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_read.tag); // error = true; // } // validate bank and share tags if (entry->m_read.m_type == AMH_BANK && !validate_tag(driver, "bank", entry->m_read.m_tag)) error = true ; if (entry->m_write.m_type == AMH_BANK && !validate_tag(driver, "bank", entry->m_write.m_tag)) error = true; if (entry->m_share != NULL && !validate_tag(driver, "share", entry->m_share)) error = true; } // release the address map global_free(map); } } return error; }
int rom_load(const struct RomModule *romp) { const struct RomModule *regionlist[REGION_MAX]; const struct RomModule *region; static struct rom_load_data romdata; int regnum; /* reset the region list */ for (regnum = 0;regnum < REGION_MAX;regnum++) regionlist[regnum] = NULL; /* reset the romdata struct */ memset(&romdata, 0, sizeof(romdata)); romdata.romstotal = count_roms(romp); /* reset the disk list */ memset(disk_handle, 0, sizeof(disk_handle)); /* determine the correct biosset to load based on options.bios string */ system_bios = determine_bios_rom(Machine->gamedrv->bios); /* loop until we hit the end */ for (region = romp, regnum = 0; region; region = rom_next_region(region), regnum++) { int regiontype = ROMREGION_GETTYPE(region); debugload("Processing region %02X (length=%X)\n", regiontype, ROMREGION_GETLENGTH(region)); /* the first entry must be a region */ if (!ROMENTRY_ISREGION(region)) { printf("Error: missing ROM_REGION header\n"); return 1; } /* if sound is disabled and it's a sound-only region, skip it */ if (Machine->sample_rate == 0 && ROMREGION_ISSOUNDONLY(region)) continue; /* allocate memory for the region */ if (new_memory_region(regiontype, ROMREGION_GETLENGTH(region), ROMREGION_GETFLAGS(region))) { printf("Error: unable to allocate memory for region %d\n", regiontype); return 1; } /* remember the base and length */ romdata.regionlength = memory_region_length(regiontype); romdata.regionbase = memory_region(regiontype); debugload("Allocated %X bytes @ %08X\n", romdata.regionlength, (int)romdata.regionbase); /* clear the region if it's requested */ if (ROMREGION_ISERASE(region)) memset(romdata.regionbase, ROMREGION_GETERASEVAL(region), romdata.regionlength); /* or if it's sufficiently small (<= 4MB) */ else if (romdata.regionlength <= 0x400000) memset(romdata.regionbase, 0, romdata.regionlength); #ifdef MAME_DEBUG /* if we're debugging, fill region with random data to catch errors */ else fill_random(romdata.regionbase, romdata.regionlength); #endif /* now process the entries in the region */ if (ROMREGION_ISROMDATA(region)) { if (!process_rom_entries(&romdata, region + 1)) return 1; } else if (ROMREGION_ISDISKDATA(region)) { if (!process_disk_entries(&romdata, region + 1)) return 1; } /* add this region to the list */ if (regiontype < REGION_MAX) regionlist[regiontype] = region; } /* post-process the regions */ for (regnum = 0; regnum < REGION_MAX; regnum++) if (regionlist[regnum]) { debugload("Post-processing region %02X\n", regnum); romdata.regionlength = memory_region_length(regnum); romdata.regionbase = memory_region(regnum); region_post_process(&romdata, regionlist[regnum]); } /* display the results and exit */ return display_rom_load_results(&romdata); }
void address_map::map_validity_check(validity_checker &valid, const device_t &device, address_spacenum spacenum) const { // it's safe to assume here that the device has a memory interface and a config for this space const address_space_config &spaceconfig = *device.memory().space_config(spacenum); int datawidth = spaceconfig.m_databus_width; int alignunit = datawidth / 8; bool detected_overlap = DETECT_OVERLAPPING_MEMORY ? false : true; // if this is an empty map, just ignore it if (m_entrylist.first() == nullptr) return; // validate the global map parameters if (m_spacenum != spacenum) osd_printf_error("Space %d has address space %d handlers!\n", spacenum, m_spacenum); if (m_databits != datawidth) osd_printf_error("Wrong memory handlers provided for %s space! (width = %d, memory = %08x)\n", spaceconfig.m_name, datawidth, m_databits); // loop over entries and look for errors for (address_map_entry &entry : m_entrylist) { UINT32 bytestart = spaceconfig.addr2byte(entry.m_addrstart); UINT32 byteend = spaceconfig.addr2byte_end(entry.m_addrend); // look for overlapping entries if (!detected_overlap) { for (address_map_entry &scan : m_entrylist) { if (&scan == &entry) break; if (entry.m_addrstart <= scan.m_addrend && entry.m_addrend >= scan.m_addrstart && ((entry.m_read.m_type != AMH_NONE && scan.m_read.m_type != AMH_NONE) || (entry.m_write.m_type != AMH_NONE && scan.m_write.m_type != AMH_NONE))) { osd_printf_warning("%s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend, entry.m_read.m_type, entry.m_write.m_type, scan.m_addrstart, scan.m_addrend, scan.m_read.m_type, scan.m_write.m_type); detected_overlap = true; break; } } } // look for inverted start/end pairs if (byteend < bytestart) osd_printf_error("Wrong %s memory read handler start = %08x > end = %08x\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend); // look for misaligned entries if ((bytestart & (alignunit - 1)) != 0 || (byteend & (alignunit - 1)) != (alignunit - 1)) osd_printf_error("Wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend, alignunit); // if this is a program space, auto-assign implicit ROM entries if (entry.m_read.m_type == AMH_ROM && entry.m_region == nullptr) { entry.m_region = device.tag(); entry.m_rgnoffs = entry.m_addrstart; } // if this entry references a memory region, validate it if (entry.m_region != nullptr && entry.m_share == nullptr) { // 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(device.mconfig().root_device())) for (const rom_entry *romp = rom_first_region(dev); romp != nullptr && !found; romp = rom_next_region(romp)) { if (rom_region_name(dev, romp) == entry_region) { // verify the address range is within the region's bounds offs_t length = ROMREGION_GETLENGTH(romp); if (entry.m_rgnoffs + (byteend - bytestart + 1) > length) osd_printf_error("%s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend, entry.m_region, length); found = true; } } // error if not found if (!found) osd_printf_error("%s space memory map entry %X-%X references non-existant region '%s'\n", spaceconfig.m_name, entry.m_addrstart, entry.m_addrend, entry.m_region); } // make sure all devices exist if (entry.m_read.m_type == AMH_DEVICE_DELEGATE) { // extract the device tag from the proto-delegate const char *devtag = nullptr; switch (entry.m_read.m_bits) { case 8: devtag = entry.m_rproto8.device_name(); break; case 16: devtag = entry.m_rproto16.device_name(); break; case 32: devtag = entry.m_rproto32.device_name(); break; case 64: devtag = entry.m_rproto64.device_name(); break; } if (entry.m_devbase.subdevice(devtag) == nullptr) osd_printf_error("%s space memory map entry reads from nonexistent device '%s'\n", spaceconfig.m_name, devtag != nullptr ? devtag : "<unspecified>"); } if (entry.m_write.m_type == AMH_DEVICE_DELEGATE) { // extract the device tag from the proto-delegate const char *devtag = nullptr; switch (entry.m_write.m_bits) { case 8: devtag = entry.m_wproto8.device_name(); break; case 16: devtag = entry.m_wproto16.device_name(); break; case 32: devtag = entry.m_wproto32.device_name(); break; case 64: devtag = entry.m_wproto64.device_name(); break; } if (entry.m_devbase.subdevice(devtag) == nullptr) osd_printf_error("%s space memory map entry writes to nonexistent device '%s'\n", spaceconfig.m_name, devtag != nullptr ? devtag : "<unspecified>"); } if (entry.m_setoffsethd.m_type == AMH_DEVICE_DELEGATE) { // extract the device tag from the proto-delegate const char *devtag = entry.m_soproto.device_name(); if (entry.m_devbase.subdevice(devtag) == nullptr) osd_printf_error("%s space memory map entry references nonexistent device '%s'\n", spaceconfig.m_name, devtag != nullptr ? devtag : "<unspecified>"); } // make sure ports exist // if ((entry.m_read.m_type == AMH_PORT && entry.m_read.m_tag != nullptr && portlist.find(entry.m_read.m_tag) == nullptr) || // (entry.m_write.m_type == AMH_PORT && entry.m_write.m_tag != nullptr && portlist.find(entry.m_write.m_tag) == nullptr)) // osd_printf_error("%s space memory map entry references nonexistent port tag '%s'\n", spaceconfig.m_name, entry.m_read.m_tag); // validate bank and share tags if (entry.m_read.m_type == AMH_BANK) valid.validate_tag(entry.m_read.m_tag); if (entry.m_write.m_type == AMH_BANK) valid.validate_tag(entry.m_write.m_tag); if (entry.m_share != nullptr) valid.validate_tag(entry.m_share); } }
void rom_init(running_machine *machine, const rom_entry *romp) { const rom_entry *regionlist[REGION_MAX]; const rom_entry *region; static rom_load_data romdata; int regnum; /* if no roms, bail */ if (romp == NULL) return; /* make sure we get called back on the way out */ add_exit_callback(machine, rom_exit); /* reset the region list */ memset((void *)regionlist, 0, sizeof(regionlist)); /* reset the romdata struct */ memset(&romdata, 0, sizeof(romdata)); romdata.romstotal = count_roms(romp); /* reset the disk list */ memset(disk_handle, 0, sizeof(disk_handle)); /* determine the correct biosset to load based on options.bios string */ system_bios = determine_bios_rom(Machine->gamedrv->bios); /* loop until we hit the end */ for (region = romp, regnum = 0; region; region = rom_next_region(region), regnum++) { int regiontype = ROMREGION_GETTYPE(region); debugload("Processing region %02X (length=%X)\n", regiontype, ROMREGION_GETLENGTH(region)); /* the first entry must be a region */ assert(ROMENTRY_ISREGION(region)); /* remember the base and length */ romdata.regionbase = new_memory_region(machine, regiontype, ROMREGION_GETLENGTH(region), ROMREGION_GETFLAGS(region)); romdata.regionlength = ROMREGION_GETLENGTH(region); debugload("Allocated %X bytes @ %08X\n", romdata.regionlength, (int)romdata.regionbase); /* clear the region if it's requested */ if (ROMREGION_ISERASE(region)) memset(romdata.regionbase, ROMREGION_GETERASEVAL(region), romdata.regionlength); /* or if it's sufficiently small (<= 4MB) */ else if (romdata.regionlength <= 0x400000) memset(romdata.regionbase, 0, romdata.regionlength); #ifdef MAME_DEBUG /* if we're debugging, fill region with random data to catch errors */ else fill_random(romdata.regionbase, romdata.regionlength); #endif /* now process the entries in the region */ if (ROMREGION_ISROMDATA(region)) process_rom_entries(&romdata, region + 1); else if (ROMREGION_ISDISKDATA(region)) process_disk_entries(&romdata, region + 1); /* add this region to the list */ if (regiontype < REGION_MAX) regionlist[regiontype] = region; } /* post-process the regions */ for (regnum = 0; regnum < REGION_MAX; regnum++) if (regionlist[regnum]) { debugload("Post-processing region %02X\n", regnum); romdata.regionlength = memory_region_length(regnum); romdata.regionbase = memory_region(regnum); region_post_process(&romdata, regionlist[regnum]); } /* display the results and exit */ total_rom_load_warnings = romdata.warnings; display_rom_load_results(&romdata); }
static int info_listsoftware(core_options *options, const char *gamename) { FILE *out = stdout; int nr_lists = 0; char ** lists = NULL; int list_idx = 0; /* First determine the maximum number of lists we might encounter */ for ( int drvindex = 0; drivers[drvindex] != NULL; drvindex++ ) { if ( mame_strwildcmp( gamename, drivers[drvindex]->name ) == 0 ) { /* allocate the machine config */ machine_config *config = global_alloc(machine_config(drivers[drvindex]->machine_config)); for (const device_config *dev = config->m_devicelist.first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) { software_list_config *swlist = (software_list_config *)downcast<const legacy_device_config_base *>(dev)->inline_config(); for ( int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++ ) { if ( swlist->list_name[i] && *swlist->list_name[i] && (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM)) nr_lists++; } } /* free the machine config */ global_free(config); } } lists = global_alloc_array( char *, nr_lists ); fprintf( out, "<?xml version=\"1.0\"?>\n" "<!DOCTYPE softwarelist [\n" "<!ELEMENT softwarelists (softwarelist*)>\n" "\t<!ELEMENT softwarelist (software+)>\n" "\t\t<!ATTLIST softwarelist name CDATA #REQUIRED>\n" "\t\t<!ATTLIST softwarelist description CDATA #IMPLIED>\n" "\t\t<!ELEMENT software (description, year?, publisher, part*)>\n" "\t\t\t<!ATTLIST software name CDATA #REQUIRED>\n" "\t\t\t<!ATTLIST software cloneof CDATA #IMPLIED>\n" "\t\t\t<!ATTLIST software supported (yes|partial|no) \"yes\">\n" "\t\t\t<!ELEMENT description (#PCDATA)>\n" "\t\t\t<!ELEMENT year (#PCDATA)>\n" "\t\t\t<!ELEMENT publisher (#PCDATA)>\n" "\t\t\t<!ELEMENT part (dataarea*)>\n" "\t\t\t\t<!ATTLIST part name CDATA #REQUIRED>\n" "\t\t\t\t<!ATTLIST part interface CDATA #REQUIRED>\n" "\t\t\t\t<!ATTLIST part feature CDATA #IMPLIED>\n" "\t\t\t\t<!ELEMENT dataarea (rom*)>\n" "\t\t\t\t\t<!ATTLIST dataarea name CDATA #REQUIRED>\n" "\t\t\t\t\t<!ATTLIST dataarea size CDATA #REQUIRED>\n" "\t\t\t\t\t<!ATTLIST dataarea databits (8|16|32|64) \"8\">\n" "\t\t\t\t\t<!ATTLIST dataarea endian (big|little) \"little\">\n" "\t\t\t\t\t<!ELEMENT rom EMPTY>\n" "\t\t\t\t\t\t<!ATTLIST rom name CDATA #IMPLIED>\n" "\t\t\t\t\t\t<!ATTLIST rom size CDATA #REQUIRED>\n" "\t\t\t\t\t\t<!ATTLIST rom crc CDATA #IMPLIED>\n" "\t\t\t\t\t\t<!ATTLIST rom md5 CDATA #IMPLIED>\n" "\t\t\t\t\t\t<!ATTLIST rom sha1 CDATA #IMPLIED>\n" "\t\t\t\t\t\t<!ATTLIST rom offset CDATA #IMPLIED>\n" "\t\t\t\t\t\t<!ATTLIST rom status (baddump|nodump|good) \"good\">\n" "\t\t\t\t\t\t<!ATTLIST rom loadflag (load16_byte|load16_word|load16_word_swap|load32_byte|load32_word|load32_word_swap|load32_dword|load64_word|load64_word_swap|reload) #IMPLIED>\n" "]>\n\n" "<softwarelists>\n" ); for ( int drvindex = 0; drivers[drvindex] != NULL; drvindex++ ) { if ( mame_strwildcmp( gamename, drivers[drvindex]->name ) == 0 ) { /* allocate the machine config */ machine_config *config = global_alloc(machine_config(drivers[drvindex]->machine_config)); for (const device_config *dev = config->m_devicelist.first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) { software_list_config *swlist = (software_list_config *)downcast<const legacy_device_config_base *>(dev)->inline_config(); for ( int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++ ) { if ( swlist->list_name[i] && *swlist->list_name[i] && (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM)) { software_list *list = software_list_open( options, swlist->list_name[i], FALSE, NULL ); if ( list ) { /* Verify if we have encountered this list before */ bool seen_before = false; for ( int l = 0; l < list_idx && !seen_before; l++ ) { if ( ! strcmp( swlist->list_name[i], lists[l] ) ) { seen_before = true; } } if ( ! seen_before ) { lists[list_idx] = core_strdup( swlist->list_name[i] ); list_idx++; fprintf(out, "\t<softwarelist name=\"%s\">\n", swlist->list_name[i] ); for ( software_info *swinfo = software_list_find( list, "*", NULL ); swinfo != NULL; swinfo = software_list_find( list, "*", swinfo ) ) { fprintf( out, "\t\t<software name=\"%s\"", swinfo->shortname ); if ( swinfo->parentname != NULL ) fprintf( out, " cloneof=\"%s\"", swinfo->parentname ); if ( swinfo->supported == SOFTWARE_SUPPORTED_PARTIAL ) fprintf( out, " supported=\"partial\"" ); if ( swinfo->supported == SOFTWARE_SUPPORTED_NO ) fprintf( out, " supported=\"no\"" ); fprintf( out, ">\n" ); fprintf( out, "\t\t\t<description>%s</description>\n", xml_normalize_string(swinfo->longname) ); fprintf( out, "\t\t\t<year>%s</year>\n", xml_normalize_string( swinfo->year ) ); fprintf( out, "\t\t\t<publisher>%s</publisher>\n", xml_normalize_string( swinfo->publisher ) ); for ( software_part *part = software_find_part( swinfo, NULL, NULL ); part != NULL; part = software_part_next( part ) ) { fprintf( out, "\t\t\t<part name=\"%s\"", part->name ); if ( part->interface_ ) fprintf( out, " interface=\"%s\"", part->interface_ ); // if ( part->feature ) // fprintf( out, " features=\"%s\"", part->feature ); fprintf( out, ">\n"); /* TODO: display rom region information */ for ( const rom_entry *region = part->romdata; region; region = rom_next_region( region ) ) { fprintf( out, "\t\t\t\t<dataarea name=\"%s\" size=\"%x\">\n", ROMREGION_GETTAG(region), ROMREGION_GETLENGTH(region) ); for ( const rom_entry *rom = rom_first_file( region ); rom && !ROMENTRY_ISREGIONEND(rom); rom++ ) { if ( ROMENTRY_ISFILE(rom) ) { fprintf( out, "\t\t\t\t\t<rom name=\"%s\" size=\"%d\"", xml_normalize_string(ROM_GETNAME(rom)), rom_file_size(rom) ); /* dump checksum information only if there is a known dump */ if (!hash_data_has_info(ROM_GETHASHDATA(rom), HASH_INFO_NO_DUMP)) { char checksum[HASH_BUF_SIZE]; int hashtype; /* iterate over hash function types and print out their values */ for (hashtype = 0; hashtype < HASH_NUM_FUNCTIONS; hashtype++) if (hash_data_extract_printable_checksum(ROM_GETHASHDATA(rom), 1 << hashtype, checksum)) fprintf(out, " %s=\"%s\"", hash_function_name(1 << hashtype), checksum); } fprintf( out, " offset=\"%x\"", ROM_GETOFFSET(rom) ); if ( hash_data_has_info(ROM_GETHASHDATA(rom), HASH_INFO_BAD_DUMP) ) fprintf( out, " status=\"baddump\"" ); if ( hash_data_has_info(ROM_GETHASHDATA(rom), HASH_INFO_NO_DUMP) ) fprintf( out, " status=\"nodump\"" ); fprintf( out, "/>\n" ); } else if ( ROMENTRY_ISRELOAD(rom) ) { fprintf( out, "\t\t\t\t\t<rom size=\"%d\" offset=\"%x\" loadflag=\"reload\" />\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) ); } } fprintf( out, "\t\t\t\t</dataarea>\n" ); } fprintf( out, "\t\t\t</part>\n" ); } fprintf( out, "\t\t</software>\n" ); } fprintf(out, "\t</softwarelist>\n" ); } software_list_close( list ); } } } } global_free(config); } } fprintf( out, "</softwarelists>\n" ); global_free( lists ); return MAMERR_NONE; }