int cartslot_image_device::load_cartridge(const rom_entry *romrgn, const rom_entry *roment, bool load) { const char *region; const char *type; UINT32 flags; offs_t offset, size, read_length, pos = 0, len; UINT8 *ptr; UINT8 clear_val; int datawidth, littleendian, i, j; device_t *cpu; astring regiontag; device().siblingtag(regiontag, ROMREGION_GETTAG(romrgn)); region = regiontag.cstr(); offset = ROM_GETOFFSET(roment); size = ROM_GETLENGTH(roment); flags = ROM_GETFLAGS(roment); ptr = ((UINT8 *) device().machine().root_device().memregion(region)->base()) + offset; if (load) { if (software_entry() == NULL) { /* must this be full size */ if (flags & ROM_FULLSIZE) { if (length() != size) return IMAGE_INIT_FAIL; } /* read the ROM */ pos = read_length = fread(ptr, size); /* reset the ROM to the initial point. */ /* eventually, we could add a flag to allow the ROM to continue instead of restarting whenever a new cart region is present */ fseek(0, SEEK_SET); } else { /* must this be full size */ if (flags & ROM_FULLSIZE) { if (get_software_region_length("rom") != size) return IMAGE_INIT_FAIL; } /* read the ROM */ pos = read_length = get_software_region_length("rom"); memcpy(ptr, get_software_region("rom"), read_length); } /* do we need to mirror the ROM? */ if (flags & ROM_MIRROR) { while(pos < size) { len = MIN(read_length, size - pos); memcpy(ptr + pos, ptr, len); pos += len; } } /* postprocess this region */ type = regiontag.cstr(); littleendian = ROMREGION_ISLITTLEENDIAN(romrgn); datawidth = ROMREGION_GETWIDTH(romrgn) / 8; /* if the region is inverted, do that now */ device_memory_interface *memory; cpu = device().machine().device(type); if (cpu!=NULL && cpu->interface(memory)) { datawidth = cpu->memory().space_config(AS_PROGRAM)->m_databus_width / 8; littleendian = (cpu->memory().space_config()->m_endianness == ENDIANNESS_LITTLE); } /* swap the endianness if we need to */ #ifdef LSB_FIRST if (datawidth > 1 && !littleendian) #else if (datawidth > 1 && littleendian) #endif { for (i = 0; i < size; i += datawidth) { UINT8 temp[8]; memcpy(temp, &ptr[i], datawidth); for (j = datawidth - 1; j >= 0; j--) ptr[i + j] = temp[datawidth - 1 - j]; } } } /* clear out anything that remains */ if (!(flags & ROM_NOCLEAR)) { clear_val = (flags & ROM_FILL_FF) ? 0xFF : 0x00; memset(ptr + pos, clear_val, size - pos); } return IMAGE_INIT_PASS; }
void info_xml_creator::output_rom(device_t &device) { // iterate over 3 different ROM "types": BIOS, ROMs, DISKs for (int rom_type = 0; rom_type < 3; rom_type++) for (const rom_entry *region = rom_first_region(device); region != NULL; region = rom_next_region(region)) { bool is_disk = ROMREGION_ISDISKDATA(region); // disk regions only work for disks if ((is_disk && rom_type != 2) || (!is_disk && rom_type == 2)) continue; // iterate through ROM entries for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) { bool is_bios = ROM_GETBIOSFLAGS(rom); const char *name = ROM_GETNAME(rom); int offset = ROM_GETOFFSET(rom); const char *merge_name = NULL; char bios_name[100]; // BIOS ROMs only apply to bioses if ((is_bios && rom_type != 0) || (!is_bios && rom_type == 0)) continue; // if we have a valid ROM and we are a clone, see if we can find the parent ROM hash_collection hashes(ROM_GETHASHDATA(rom)); if (!hashes.flag(hash_collection::FLAG_NO_DUMP)) merge_name = get_merge_name(hashes); if (&device != &m_drivlist.config().root_device()) merge_name = NULL; // scan for a BIOS name bios_name[0] = 0; if (!is_disk && is_bios) { // scan backwards through the ROM entries for (const rom_entry *brom = rom - 1; brom != m_drivlist.driver().rom; brom--) if (ROMENTRY_ISSYSTEM_BIOS(brom)) { strcpy(bios_name, ROM_GETNAME(brom)); break; } } std::string output; // opening tag if (!is_disk) output.append("\t\t<rom"); else output.append("\t\t<disk"); // add name, merge, bios, and size tags */ if (name != NULL && name[0] != 0) strcatprintf(output," name=\"%s\"", xml_normalize_string(name)); if (merge_name != NULL) strcatprintf(output," merge=\"%s\"", xml_normalize_string(merge_name)); if (bios_name[0] != 0) strcatprintf(output," bios=\"%s\"", xml_normalize_string(bios_name)); if (!is_disk) strcatprintf(output," size=\"%d\"", rom_file_size(rom)); // dump checksum information only if there is a known dump if (!hashes.flag(hash_collection::FLAG_NO_DUMP)) { // iterate over hash function types and print m_output their values std::string tempstr; strcatprintf(output," %s", hashes.attribute_string(tempstr)); } else output.append(" status=\"nodump\""); // append a region name strcatprintf(output," region=\"%s\"", ROMREGION_GETTAG(region)); // for non-disk entries, print offset if (!is_disk) strcatprintf(output," offset=\"%x\"", offset); // for disk entries, add the disk index else { strcatprintf(output," index=\"%x\"", DISK_GETINDEX(rom)); strcatprintf(output," writable=\"%s\"", DISK_ISREADONLY(rom) ? "no" : "yes"); } // add optional flag if (ROM_ISOPTIONAL(rom)) output.append(" optional=\"yes\""); output.append("/>\n"); fprintf(m_output, "%s", output.c_str()); } } }
bool device_config_memory_interface::interface_validity_check(emu_options &options, const game_driver &driver) const { const device_config *devconfig = &m_device_config; 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(*devconfig, 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, devconfig->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, devconfig->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, devconfig->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 = devconfig->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(m_machine_config); 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 = ROMREGION_GETTAG(romp); if (regiontag != NULL) { astring fulltag; rom_region_name(fulltag, &driver, source, romp); if (fulltag.cmp(entry->m_region) == 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, devconfig->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, devconfig->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 && m_machine_config.m_devicelist.find(entry->m_read.m_tag) == NULL) || (entry->m_write.m_type == AMH_LEGACY_DEVICE_HANDLER && entry->m_write.m_tag != NULL && m_machine_config.m_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, devconfig->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, devconfig->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; }
void rom_load_manager::load_software_part_region(device_t &device, software_list_device &swlist, const char *swname, const rom_entry *start_region) { std::string locationtag(swlist.list_name()), breakstr("%"); const rom_entry *region; std::string regiontag; m_errorstring.clear(); m_softwarningstring.clear(); m_romstotal = 0; m_romstotalsize = 0; m_romsloadedsize = 0; software_info *swinfo = swlist.find(swname); if (swinfo != nullptr) { UINT32 supported = swinfo->supported(); if (supported == SOFTWARE_SUPPORTED_PARTIAL) { m_errorstring.append(string_format("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist.list_name())); m_softwarningstring.append(string_format("Support for software %s (in list %s) is only partial\n", swname, swlist.list_name())); } if (supported == SOFTWARE_SUPPORTED_NO) { m_errorstring.append(string_format("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist.list_name())); m_softwarningstring.append(string_format("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 std::string in the format // " swlist % clonename % parentname " // open_rom_file contains the code to split the elements and to create paths to load from locationtag.append(breakstr); while (swinfo != nullptr) { locationtag.append(swinfo->shortname()).append(breakstr); const char *parentname = swinfo->parentname(); swinfo = (parentname != nullptr) ? swlist.find(parentname) : nullptr; } // strip the final '%' locationtag.erase(locationtag.length() - 1, 1); } /* loop until we hit the end */ for (region = start_region; region != nullptr; region = rom_next_region(region)) { UINT32 regionlength = ROMREGION_GETLENGTH(region); regiontag = device.subtag(ROMREGION_GETTAG(region)); LOG(("Processing region \"%s\" (length=%X)\n", regiontag.c_str(), 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 = machine().root_device().memregion(regiontag.c_str()); if (memregion != nullptr) { if (machine().device(regiontag.c_str()) != nullptr) normalize_flags_for_device(machine(), regiontag.c_str(), width, endianness); /* clear old region (todo: should be moved to an image unload function) */ machine().memory().region_free(memregion->name()); } /* 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 /* update total number of roms */ for (const rom_entry *rom = rom_first_file(region); rom != nullptr; rom = rom_next_file(rom)) { m_romstotal++; m_romstotalsize += rom_file_size(rom); } /* now process the entries in the region */ if (ROMREGION_ISROMDATA(region)) process_rom_entries(locationtag.c_str(), region, region + 1, &device, TRUE); else if (ROMREGION_ISDISKDATA(region)) process_disk_entries(regiontag.c_str(), region, region + 1, locationtag.c_str()); } /* now go back and post-process all the regions */ for (region = start_region; region != nullptr; region = rom_next_region(region)) { regiontag = device.subtag(ROMREGION_GETTAG(region)); region_post_process(regiontag.c_str(), ROMREGION_ISINVERTED(region)); } /* display the results and exit */ display_rom_load_results(TRUE); }
void load_software_part_region(device_t *device, char *swlist, char *swname, rom_entry *start_region) { astring locationtag(swlist), breakstr("%"); rom_load_data *romdata = device->machine().romload_data; const rom_entry *region; astring regiontag; // 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 software_list *software_list_ptr = software_list_open(device->machine().options(), swlist, FALSE, NULL); if (software_list_ptr) { locationtag.cat(breakstr); for (software_info *swinfo = software_list_find(software_list_ptr, swname, NULL); swinfo != NULL; ) { { astring tmp(swinfo->shortname); locationtag.cat(tmp); locationtag.cat(breakstr); // printf("%s\n", locationtag.cstr()); } const char *parentname = software_get_clone(device->machine().options(), swlist, swinfo->shortname); if (parentname != NULL) swinfo = software_list_find(software_list_ptr, parentname, NULL); else swinfo = NULL; } // strip the final '%' locationtag.del(locationtag.len() - 1, 1); software_list_close(software_list_ptr); } /* Make sure we are passed a device */ assert(device != NULL); romdata->errorstring.reset(); if (software_get_support(device->machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_PARTIAL) { romdata->errorstring.catprintf("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist); romdata->warnings++; } if (software_get_support(device->machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_NO) { romdata->errorstring.catprintf("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist); romdata->warnings++; } /* 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 /* now process the entries in the region */ if (ROMREGION_ISROMDATA(region)) process_rom_entries(romdata, locationtag, region, region + 1); 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); }
media_auditor::summary media_auditor::audit_media(const char *validation) { // start fresh m_record_list.reset(); // store validation for later m_validation = validation; // temporary hack until romload is update: get the driver path and support it for // all searches const char *driverpath = m_enumerator.config().devicelist().find("root")->searchpath(); // iterate over ROM sources and regions int found = 0; int required = 0; int sharedFound = 0; int sharedRequired = 0; for (const rom_source *source = rom_first_source(m_enumerator.config()); source != NULL; source = rom_next_source(*source)) { // determine the search path for this source and iterate through the regions m_searchpath = source->searchpath(); // also determine if this is the driver's specific ROMs or not bool source_is_gamedrv = (dynamic_cast<const driver_device *>(source) != NULL); // now iterate over regions and ROMs within for (const rom_entry *region = rom_first_region(*source); region != NULL; region = rom_next_region(region)) { // temporary hack: add the driver path & region name astring combinedpath(source->searchpath(), ";", driverpath); if(ROMREGION_ISLOADBYNAME(region)) { combinedpath=combinedpath.cat(";"); combinedpath=combinedpath.cat(ROMREGION_GETTAG(region)); } m_searchpath = combinedpath; for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { hash_collection hashes(ROM_GETHASHDATA(rom)); bool shared = also_used_by_parent(hashes) >= 0; // if a dump exists, then at least one entry is required if (!hashes.flag(hash_collection::FLAG_NO_DUMP)) { required++; if (shared) { sharedRequired++; } } // audit a file audit_record *record = NULL; if (ROMREGION_ISROMDATA(region)) record = audit_one_rom(rom); // audit a disk else if (ROMREGION_ISDISKDATA(region)) record = audit_one_disk(rom); // skip if no record if (record == NULL) continue; // if we got a record back, if (record->status() != audit_record::STATUS_NOT_FOUND && source_is_gamedrv) { found++; if (shared) { sharedFound++; } } } } } // if we found nothing unique to this set & the set needs roms that aren't in the parent or the parent isn't found either, then we don't have the set at all if (found == sharedFound && required > 0 && (required != sharedRequired || sharedFound == 0)) m_record_list.reset(); // return a summary return summarize(); }
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; }