int audit_images(int game, UINT32 validation, audit_record **audit) { const game_driver *gamedrv = drivers[game]; const rom_entry *region, *rom; audit_record *record; int foundany = FALSE; int allshared = TRUE; int records; /* determine the number of records we will generate */ records = 0; for (region = rom_first_region(gamedrv); region != NULL; region = rom_next_region(region)) for (rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) if (ROMREGION_ISROMDATA(region) || ROMREGION_ISDISKDATA(region)) { if (allshared && !rom_used_by_parent(gamedrv, rom, NULL)) allshared = FALSE; records++; } if (records > 0) { /* allocate memory for the records */ *audit = malloc_or_die(sizeof(**audit) * records); memset(*audit, 0, sizeof(**audit) * records); record = *audit; /* iterate over regions and ROMs */ for (region = rom_first_region(drivers[game]); region; region = rom_next_region(region)) for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { int shared = rom_used_by_parent(gamedrv, rom, NULL); /* audit a file */ if (ROMREGION_ISROMDATA(region)) { if (audit_one_rom(rom, gamedrv, validation, record++) && (!shared || allshared)) foundany = TRUE; } /* audit a disk */ else if (ROMREGION_ISDISKDATA(region)) { if (audit_one_disk(rom, gamedrv, validation, record++) && (!shared || allshared)) foundany = TRUE; } } /* if we found nothing, we don't have the set at all */ if (!foundany) { free(*audit); *audit = NULL; records = 0; } } return records; }
int cli_info_listcrc(core_options *options, const char *gamename) { int drvindex, count = 0; /* iterate over drivers */ for (drvindex = 0; drivers[drvindex]; drvindex++) if (mame_strwildcmp(gamename, drivers[drvindex]->name) == 0) { const rom_entry *region, *rom; /* iterate over regions, and then ROMs within the region */ for (region = rom_first_region(drivers[drvindex]); region; region = rom_next_region(region)) for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { char hashbuf[HASH_BUF_SIZE]; /* if we have a CRC, display it */ if (hash_data_extract_printable_checksum(ROM_GETHASHDATA(rom), HASH_CRC, hashbuf)) mame_printf_info("%s %-12s %s\n", hashbuf, ROM_GETNAME(rom), drivers[drvindex]->description); } count++; } /* return an error if none found */ return (count > 0) ? MAMERR_NONE : MAMERR_NO_SUCH_GAME; }
static void match_roms(core_options *options, const char *hash, int length, int *found) { int drvindex; /* iterate over drivers */ for (drvindex = 0; drivers[drvindex] != NULL; drvindex++) { machine_config *config = global_alloc(machine_config(drivers[drvindex]->machine_config)); const rom_entry *region, *rom; const rom_source *source; /* iterate over sources, regions and files within the region */ for (source = rom_first_source(drivers[drvindex], config); source != NULL; source = rom_next_source(drivers[drvindex], config, source)) for (region = rom_first_region(drivers[drvindex], source); region; region = rom_next_region(region)) for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) if (hash_data_is_equal(hash, ROM_GETHASHDATA(rom), 0)) { int baddump = hash_data_has_info(ROM_GETHASHDATA(rom), HASH_INFO_BAD_DUMP); /* output information about the match */ if (*found != 0) mame_printf_info(" "); mame_printf_info("= %s%-20s %-10s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), drivers[drvindex]->name, drivers[drvindex]->description); (*found)++; } global_free(config); } softlist_match_roms( options, hash, length, found ); }
BOOL DriverUsesRoms(int driver_index) { const struct GameDriver *gamedrv = drivers[driver_index]; const struct RomModule *region, *rom; for (region = rom_first_region(gamedrv); region; region = rom_next_region(region)) for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) return TRUE; return FALSE; }
/* returns 1 if rom is defined in this set */ int audit_is_rom_used (const game_driver *gamedrv, const char* hash) { const rom_entry *region, *rom; for (region = rom_first_region(gamedrv); region; region = rom_next_region(region)) for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) /* Compare all the available checksums */ if (hash_data_is_equal(ROM_GETHASHDATA(rom), hash, 0)) return 1; return 0; }
/* returns 1 if rom is defined in this set */ int RomInSet (const struct GameDriver *gamedrv, const char* hash) { const struct RomModule *region, *rom; for (region = rom_first_region(gamedrv); region; region = rom_next_region(region)) for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) /* Compare all the available checksums */ if (hash_data_is_equal(ROM_GETHASHDATA(rom), hash, 0)) return 1; return 0; }
device_t *media_auditor::find_shared_device(device_t &device, const hash_collection &romhashes, UINT64 romlength) { // doesn't apply to NO_DUMP items if (romhashes.flag(hash_collection::FLAG_NO_DUMP)) return NULL; // special case for non-root devices device_t *highest_device = NULL; if (device.owner() != NULL) { for (const rom_entry *region = rom_first_region(device); region != NULL; region = rom_next_region(region)) for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) if (ROM_GETLENGTH(rom) == romlength) { hash_collection hashes(ROM_GETHASHDATA(rom)); if (hashes == romhashes) highest_device = &device; } } else { // iterate up the parent chain for (int drvindex = m_enumerator.find(m_enumerator.driver().parent); drvindex != -1; drvindex = m_enumerator.find(m_enumerator.driver(drvindex).parent)) { device_iterator deviter(m_enumerator.config(drvindex).root_device()); for (device_t *scandevice = deviter.first(); scandevice != NULL; scandevice = deviter.next()) for (const rom_entry *region = rom_first_region(*scandevice); region; region = rom_next_region(region)) for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom)) if (ROM_GETLENGTH(rom) == romlength) { hash_collection hashes(ROM_GETHASHDATA(rom)); if (hashes == romhashes) highest_device = scandevice; } } } return highest_device; }
media_auditor::summary media_auditor::audit_device(device_t *device, const char *validation) { // start fresh m_record_list.reset(); // store validation for later m_validation = validation; m_searchpath = device->shortname(); int found = 0; int required = 0; // now iterate over regions and ROMs within for (const rom_entry *region = rom_first_region(*device); region != nullptr; region = rom_next_region(region)) { for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { hash_collection hashes(ROM_GETHASHDATA(rom)); // count the number of files with hashes if (!hashes.flag(hash_collection::FLAG_NO_DUMP) && !ROM_ISOPTIONAL(rom)) { required++; } // audit a file audit_record *record = nullptr; if (ROMREGION_ISROMDATA(region)) record = audit_one_rom(rom); // audit a disk else if (ROMREGION_ISDISKDATA(region)) record = audit_one_disk(rom); // count the number of files that are found. if (record != nullptr && (record->status() == audit_record::STATUS_GOOD || record->status() == audit_record::STATUS_FOUND_INVALID)) { found++; } } } if (found == 0 && required > 0) { m_record_list.reset(); return NOTFOUND; } // return a summary return summarize(device->shortname()); }
void printromlist(const struct RomModule *romp,const char *basename) { const struct RomModule *region, *rom, *chunk; char buf[512]; if (!romp) return; #ifdef MESS if (!strcmp(basename,"nes")) return; #endif printf("This is the list of the ROMs required for driver \"%s\".\n" "Name Size Checksum\n",basename); for (region = romp; region; region = rom_next_region(region)) { for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { const char *name = ROM_GETNAME(rom); const char* hash = ROM_GETHASHDATA(rom); int length = -1; /* default is for disks! */ if (ROMREGION_ISROMDATA(region)) { length = 0; for (chunk = rom_first_chunk(rom); chunk; chunk = rom_next_chunk(chunk)) length += ROM_GETLENGTH(chunk); } printf("%-12s ", name); if (length >= 0) printf("%7d",length); else printf(" "); if (!hash_data_has_info(hash, HASH_INFO_NO_DUMP)) { if (hash_data_has_info(hash, HASH_INFO_BAD_DUMP)) printf(" BAD"); hash_data_print(hash, 0, buf); printf(" %s", buf); } else printf(" NO GOOD DUMP KNOWN"); printf("\n"); } } }
/*------------------------------------------------- softlist_match_roms - scan for a matching software ROM by hash -------------------------------------------------*/ static void softlist_match_roms(core_options *options, const char *hash, int length, int *found) { int drvindex; /* iterate over drivers */ for (drvindex = 0; drivers[drvindex] != NULL; drvindex++) { 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] ) { software_list *list = software_list_open( options, swlist->list_name[i], FALSE, NULL ); for ( software_info *swinfo = software_list_find( list, "*", NULL ); swinfo != NULL; swinfo = software_list_find( list, "*", swinfo ) ) { for ( software_part *part = software_find_part( swinfo, NULL, NULL ); part != NULL; part = software_part_next( part ) ) { for ( const rom_entry *region = part->romdata; region != NULL; region = rom_next_region(region) ) { for ( const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom) ) { if ( hash_data_is_equal(hash, ROM_GETHASHDATA(rom), 0) ) { int baddump = hash_data_has_info(ROM_GETHASHDATA(rom), HASH_INFO_BAD_DUMP); /* output information about the match */ if (*found != 0) mame_printf_info(" "); mame_printf_info("= %s%-20s %s:%s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), swlist->list_name[i], swinfo->shortname, swinfo->longname); (*found)++; } } } } } software_list_close( list ); } } } global_free(config); } }
device_t *media_auditor::find_shared_device(device_t &device, const char *name, const hash_collection &romhashes, UINT64 romlength) { bool dumped = !romhashes.flag(hash_collection::FLAG_NO_DUMP); // special case for non-root devices device_t *highest_device = nullptr; if (device.owner() != nullptr) { for (const rom_entry *region = rom_first_region(device); region != nullptr; region = rom_next_region(region)) for (const rom_entry *rom = rom_first_file(region); rom != nullptr; rom = rom_next_file(rom)) if (ROM_GETLENGTH(rom) == romlength) { hash_collection hashes(ROM_GETHASHDATA(rom)); if ((dumped && hashes == romhashes) || (!dumped && ROM_GETNAME(rom) == name)) highest_device = &device; } } else { // iterate up the parent chain for (int drvindex = m_enumerator.find(m_enumerator.driver().parent); drvindex != -1; drvindex = m_enumerator.find(m_enumerator.driver(drvindex).parent)) { device_iterator deviter(m_enumerator.config(drvindex).root_device()); for (device_t *scandevice = deviter.first(); scandevice != nullptr; scandevice = deviter.next()) for (const rom_entry *region = rom_first_region(*scandevice); region; region = rom_next_region(region)) for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom)) if (ROM_GETLENGTH(rom) == romlength) { hash_collection hashes(ROM_GETHASHDATA(rom)); if ((dumped && hashes == romhashes) || (!dumped && ROM_GETNAME(rom) == name)) highest_device = scandevice; } } } return highest_device; }
static int count_roms(const struct RomModule *romp) { const struct RomModule *region, *rom; int count = 0; /* determine the correct biosset to load based on options.bios string */ int this_bios = determine_bios_rom(Machine->gamedrv->bios); /* loop over regions, then over files */ for (region = romp; region; region = rom_next_region(region)) for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) if (!ROM_GETBIOSFLAGS(romp) || (ROM_GETBIOSFLAGS(romp) == (this_bios+1))) /* alternate bios sets */ count++; /* return the total count */ return count; }
void rom_load_manager::count_roms() { const rom_entry *region, *rom; /* start with 0 */ m_romstotal = 0; m_romstotalsize = 0; /* loop over regions, then over files */ for (device_t &device : device_iterator(machine().config().root_device())) for (region = rom_first_region(device); region != nullptr; region = rom_next_region(region)) for (rom = rom_first_file(region); rom != nullptr; rom = rom_next_file(rom)) if (ROM_GETBIOSFLAGS(rom) == 0 || ROM_GETBIOSFLAGS(rom) == device.system_bios()) { m_romstotal++; m_romstotalsize += rom_file_size(rom); } }
int media_auditor::also_used_by_parent(const hash_collection &romhashes) { // iterate up the parent chain for (int drvindex = m_enumerator.find(m_enumerator.driver().parent); drvindex != -1; drvindex = m_enumerator.find(m_enumerator.driver(drvindex).parent)) // see if the parent has the same ROM or not for (const rom_source *source = rom_first_source(m_enumerator.config(drvindex)); source != NULL; source = rom_next_source(*source)) for (const rom_entry *region = rom_first_region(*source); region; region = rom_next_region(region)) for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { hash_collection hashes(ROM_GETHASHDATA(rom)); if (!hashes.flag(hash_collection::FLAG_NO_DUMP) && hashes == romhashes) return drvindex; } // nope, return -1 return -1; }
static void count_roms(romload_private *romdata) { const rom_entry *region, *rom; /* start with 0 */ romdata->romstotal = 0; romdata->romstotalsize = 0; /* loop over regions, then over files */ device_iterator deviter(romdata->machine().config().root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) for (region = rom_first_region(*device); region != NULL; region = rom_next_region(region)) for (rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) if (ROM_GETBIOSFLAGS(rom) == 0 || ROM_GETBIOSFLAGS(rom) == device->system_bios()) { romdata->romstotal++; romdata->romstotalsize += rom_file_size(rom); } }
const char *info_xml_creator::get_merge_name(const hash_collection &romhashes) { const char *merge_name = NULL; // walk the parent chain for (int clone_of = m_drivlist.find(m_drivlist.driver().parent); clone_of != -1; clone_of = m_drivlist.find(m_drivlist.driver(clone_of).parent)) // look in the parent's ROMs for (const rom_source *psource = rom_first_source(m_drivlist.config(clone_of,m_lookup_options)); psource != NULL; psource = rom_next_source(*psource)) for (const rom_entry *pregion = rom_first_region(*psource); pregion != NULL; pregion = rom_next_region(pregion)) for (const rom_entry *prom = rom_first_file(pregion); prom != NULL; prom = rom_next_file(prom)) { hash_collection phashes(ROM_GETHASHDATA(prom)); if (!phashes.flag(hash_collection::FLAG_NO_DUMP) && romhashes == phashes) { // stop when we find a match merge_name = ROM_GETNAME(prom); break; } } return merge_name; }
chd_error open_disk_image(const game_driver *gamedrv, const rom_entry *romp, chd_file **image) { const game_driver *drv; const rom_entry *region, *rom; const char *fname; chd_error err; /* attempt to open the properly named file */ fname = assemble_2_strings(ROM_GETNAME(romp), ".chd"); err = chd_open(fname, CHD_OPEN_READ, NULL, image); free((void *)fname); /* if that worked, we're done */ if (err == CHDERR_NONE) return err; /* otherwise, look at our parents for a CHD with an identical checksum */ /* and try to open that */ for (drv = gamedrv; drv != NULL; drv = driver_get_clone(drv)) for (region = rom_first_region(drv); region != NULL; region = rom_next_region(region)) if (ROMREGION_ISDISKDATA(region)) for (rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) /* look for a differing name but with the same hash data */ if (strcmp(ROM_GETNAME(romp), ROM_GETNAME(rom)) != 0 && hash_data_is_equal(ROM_GETHASHDATA(romp), ROM_GETHASHDATA(rom), 0)) { fname = assemble_2_strings(ROM_GETNAME(rom), ".chd"); err = chd_open(fname, CHD_OPEN_READ, NULL, image); free((void *)fname); /* if that worked, we're done */ if (err == CHDERR_NONE) return err; } return err; }
/* Identifies a rom from from this checksum */ static void match_roms(const struct GameDriver *driver,const char* hash,int *found) { const struct RomModule *region, *rom; for (region = rom_first_region(driver); region; region = rom_next_region(region)) { for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { if (hash_data_is_equal(hash, ROM_GETHASHDATA(rom), 0)) { char baddump = hash_data_has_info(ROM_GETHASHDATA(rom), HASH_INFO_BAD_DUMP); if (!silentident) { if (*found != 0) fprintf(stdout_file, " "); fprintf(stdout_file, "= %s%-12s %s\n",baddump ? "(BAD) " : "",ROM_GETNAME(rom),driver->description); } (*found)++; } } } }
static void match_roms(const char *hash, int length, int *found) { int drvindex; /* iterate over drivers */ for (drvindex = 0; drivers[drvindex]; drvindex++) { const rom_entry *region, *rom; /* iterate over regions and files within the region */ for (region = rom_first_region(drivers[drvindex]); region; region = rom_next_region(region)) for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) if (hash_data_is_equal(hash, ROM_GETHASHDATA(rom), 0)) { int baddump = hash_data_has_info(ROM_GETHASHDATA(rom), HASH_INFO_BAD_DUMP); /* output information about the match */ if (*found != 0) mame_printf_info(" "); mame_printf_info("= %s%-20s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), drivers[drvindex]->description); (*found)++; } } }
static int rom_used_by_parent(const game_driver *gamedrv, const rom_entry *romentry, const game_driver **parent) { const char *hash = ROM_GETHASHDATA(romentry); const game_driver *drv; /* iterate up the parent chain */ for (drv = driver_get_clone(gamedrv); drv != NULL; drv = driver_get_clone(drv)) { const rom_entry *region; const rom_entry *rom; /* see if the parent has the same ROM or not */ for (region = rom_first_region(drv, NULL); region; region = rom_next_region(region)) for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) if (hash_data_is_equal(ROM_GETHASHDATA(rom), hash, 0)) { if (parent != NULL) *parent = drv; return TRUE; } } return FALSE; }
int audit_images(core_options *options, const game_driver *gamedrv, UINT32 validation, audit_record **audit) { machine_config *config = global_alloc(machine_config(gamedrv->machine_config)); const rom_entry *region, *rom; const rom_source *source; audit_record *record; int anyfound = FALSE; int anyrequired = FALSE; int allshared = TRUE; int records; /* determine the number of records we will generate */ records = 0; for (source = rom_first_source(gamedrv, config); source != NULL; source = rom_next_source(gamedrv, config, source)) { int source_is_gamedrv = rom_source_is_gamedrv(gamedrv, source); for (region = rom_first_region(gamedrv, source); region != NULL; region = rom_next_region(region)) for (rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) if (ROMREGION_ISROMDATA(region) || ROMREGION_ISDISKDATA(region)) { if (source_is_gamedrv && !ROM_ISOPTIONAL(rom) && !ROM_NOGOODDUMP(rom)) { anyrequired = TRUE; if (allshared && !rom_used_by_parent(gamedrv, rom, NULL)) allshared = FALSE; } records++; } } if (records > 0) { /* allocate memory for the records */ *audit = global_alloc_array_clear(audit_record, records); record = *audit; /* iterate over ROM sources and regions */ for (source = rom_first_source(gamedrv, config); source != NULL; source = rom_next_source(gamedrv, config, source)) { int source_is_gamedrv = rom_source_is_gamedrv(gamedrv, source); for (region = rom_first_region(gamedrv, source); region != NULL; region = rom_next_region(region)) { const char *regiontag = ROMREGION_ISLOADBYNAME(region) ? ROM_GETNAME(region) : NULL; for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { /* audit a file */ if (ROMREGION_ISROMDATA(region)) { audit_one_rom(options, rom, regiontag, gamedrv, validation, record); } /* audit a disk */ else if (ROMREGION_ISDISKDATA(region)) { audit_one_disk(options, rom, gamedrv, validation, record); } else { continue; } if (source_is_gamedrv && record->status != AUDIT_STATUS_NOT_FOUND && (allshared || !rom_used_by_parent(gamedrv, rom, NULL))) anyfound = TRUE; record++; } } } } /* if we found nothing, we don't have the set at all */ if (!anyfound && anyrequired) { global_free(*audit); *audit = NULL; records = 0; } global_free(config); return records; }
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().root_device().searchpath(); int found = 0; int required = 0; int shared_found = 0; int shared_required = 0; // iterate over devices and regions device_iterator deviter(m_enumerator.config().root_device()); for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) { // determine the search path for this source and iterate through the regions m_searchpath = device->searchpath(); // now iterate over regions and ROMs within for (const rom_entry *region = rom_first_region(*device); region != nullptr; region = rom_next_region(region)) { // temporary hack: add the driver path & region name std::string combinedpath = std::string(device->searchpath()).append(";").append(driverpath); if (device->shortname()) combinedpath.append(";").append(device->shortname()); m_searchpath = combinedpath.c_str(); for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { const char *name = ROM_GETNAME(rom); hash_collection hashes(ROM_GETHASHDATA(rom)); device_t *shared_device = find_shared_device(*device, name, hashes, ROM_GETLENGTH(rom)); // count the number of files with hashes if (!hashes.flag(hash_collection::FLAG_NO_DUMP) && !ROM_ISOPTIONAL(rom)) { required++; if (shared_device != nullptr) shared_required++; } // audit a file audit_record *record = nullptr; if (ROMREGION_ISROMDATA(region)) record = audit_one_rom(rom); // audit a disk else if (ROMREGION_ISDISKDATA(region)) record = audit_one_disk(rom); if (record != nullptr) { // count the number of files that are found. if (record->status() == audit_record::STATUS_GOOD || (record->status() == audit_record::STATUS_FOUND_INVALID && find_shared_device(*device, name, record->actual_hashes(), record->actual_length()) == nullptr)) { found++; if (shared_device != nullptr) shared_found++; } record->set_shared_device(shared_device); } } } } // if we only find files that are in the parent & either the set has no unique files or the parent is not found, then assume we don't have the set at all if (found == shared_found && required > 0 && (required != shared_required || shared_found == 0)) { m_record_list.reset(); return NOTFOUND; } // return a summary return summarize(m_enumerator.driver().name); }
//------------------------------------------------- // audit_software //------------------------------------------------- media_auditor::summary media_auditor::audit_software(const char *list_name, software_info *swinfo, const char *validation) { // start fresh m_record_list.reset(); // store validation for later m_validation = validation; std::string combinedpath(swinfo->shortname()); combinedpath.append(";"); combinedpath.append(list_name); combinedpath.append(PATH_SEPARATOR); combinedpath.append(swinfo->shortname()); std::string locationtag(list_name); locationtag.append("%"); locationtag.append(swinfo->shortname()); locationtag.append("%"); if (swinfo->parentname() != nullptr) { locationtag.append(swinfo->parentname()); combinedpath.append(";").append(swinfo->parentname()).append(";").append(list_name).append(PATH_SEPARATOR).append(swinfo->parentname()); } m_searchpath = combinedpath.c_str(); int found = 0; int required = 0; // now iterate over software parts for (software_part &part : swinfo->parts()) { // now iterate over regions for ( const rom_entry *region = part.romdata(); region; region = rom_next_region( region ) ) { // now iterate over rom definitions for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { hash_collection hashes(ROM_GETHASHDATA(rom)); // count the number of files with hashes if (!hashes.flag(hash_collection::FLAG_NO_DUMP) && !ROM_ISOPTIONAL(rom)) { required++; } // audit a file audit_record *record = nullptr; if (ROMREGION_ISROMDATA(region)) { record = audit_one_rom(rom); } // audit a disk else if (ROMREGION_ISDISKDATA(region)) { record = audit_one_disk(rom, locationtag.c_str()); } // count the number of files that are found. if (record != nullptr && (record->status() == audit_record::STATUS_GOOD || record->status() == audit_record::STATUS_FOUND_INVALID)) { found++; } } } } if (found == 0 && required > 0) { m_record_list.reset(); return NOTFOUND; } // return a summary return summarize(list_name); }
int cli_info_listroms(core_options *options, const char *gamename) { int drvindex, count = 0; /* iterate over drivers */ for (drvindex = 0; drivers[drvindex]; drvindex++) if (mame_strwildcmp(gamename, drivers[drvindex]->name) == 0) { const rom_entry *region, *rom, *chunk; /* print the header */ if (count > 0) mame_printf_info("\n"); mame_printf_info("This is the list of the ROMs required for driver \"%s\".\n" "Name Size Checksum\n", drivers[drvindex]->name); /* iterate over regions and then ROMs within the region */ for (region = drivers[drvindex]->rom; region; region = rom_next_region(region)) for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { const char *name = ROM_GETNAME(rom); const char* hash = ROM_GETHASHDATA(rom); char hashbuf[HASH_BUF_SIZE]; int length = -1; /* accumulate the total length of all chunks */ if (ROMREGION_ISROMDATA(region)) { length = 0; for (chunk = rom_first_chunk(rom); chunk; chunk = rom_next_chunk(chunk)) length += ROM_GETLENGTH(chunk); } /* start with the name */ mame_printf_info("%-12s ", name); /* output the length next */ if (length >= 0) mame_printf_info("%7d", length); else mame_printf_info(" "); /* output the hash data */ if (!hash_data_has_info(hash, HASH_INFO_NO_DUMP)) { if (hash_data_has_info(hash, HASH_INFO_BAD_DUMP)) mame_printf_info(" BAD"); hash_data_print(hash, 0, hashbuf); mame_printf_info(" %s", hashbuf); } else mame_printf_info(" NO GOOD DUMP KNOWN"); /* end with a CR */ mame_printf_info("\n"); } count++; } return (count > 0) ? MAMERR_NONE : MAMERR_NO_SUCH_GAME; }
int load_driver_mameinfo(const game_driver *drv, char *buffer, int bufsize, int filenum) { machine_config config(*drv, MameUIGlobal()); const game_driver *parent = NULL; char name[512]; int mameinfo = 0; int is_bios = 0; *buffer = 0; if (filenum) snprintf(filename, ARRAY_LENGTH(filename), "%s\\messinfo.dat", GetDatsDir()); else snprintf(filename, ARRAY_LENGTH(filename), "%s\\mameinfo.dat", GetDatsDir()); if (filenum) strcat(buffer, "\n**** MESSINFO: ****\n\n"); else strcat(buffer, "\n**** MAMEINFO: ****\n\n"); /* List the game info 'flags' */ if (drv->flags & MACHINE_NOT_WORKING) strcat(buffer, "THIS GAME DOESN'T WORK PROPERLY\n"); if (drv->flags & MACHINE_UNEMULATED_PROTECTION) strcat(buffer, "The game has protection which isn't fully emulated.\n"); if (drv->flags & MACHINE_IMPERFECT_GRAPHICS) strcat(buffer, "The video emulation isn't 100% accurate.\n"); if (drv->flags & MACHINE_WRONG_COLORS) strcat(buffer, "The colors are completely wrong.\n"); if (drv->flags & MACHINE_IMPERFECT_COLORS) strcat(buffer, "The colors aren't 100% accurate.\n"); if (drv->flags & MACHINE_NO_SOUND) strcat(buffer, "The game lacks sound.\n"); if (drv->flags & MACHINE_IMPERFECT_SOUND) strcat(buffer, "The sound emulation isn't 100% accurate.\n"); if (drv->flags & MACHINE_SUPPORTS_SAVE) strcat(buffer, "Save state support.\n"); if (drv->flags & MACHINE_MECHANICAL) strcat(buffer, "The game contains mechanical parts.\n"); strcat(buffer, "\n"); if (drv->flags & MACHINE_IS_BIOS_ROOT) is_bios = 1; /* try to open mameinfo datafile */ if (ParseOpen(filename)) { if (filenum) { /* create index if necessary */ if (mess_idx) mameinfo = 1; else mameinfo = (index_datafile (&mess_idx, 0) != 0); /* load informational text (append) */ if (mess_idx) { int len = strlen(buffer); int err = 0; const game_driver *gdrv; gdrv = drv; do { err = load_datafile_text(gdrv, buffer + len, bufsize - len, mess_idx, DATAFILE_TAG_MAME, 0, 1); int g = driver_list::clone(*gdrv); if (g!=-1) gdrv = &driver_list::driver(g); else gdrv = NULL; } while (err && gdrv); if (err) mameinfo = 0; } } else { /* create index if necessary */ if (mame_idx) mameinfo = 1; else mameinfo = (index_datafile (&mame_idx, 0) != 0); /* load informational text (append) */ if (mame_idx) { int len = strlen(buffer); int err = 0; const game_driver *gdrv; gdrv = drv; do { err = load_datafile_text(gdrv, buffer + len, bufsize - len, mame_idx, DATAFILE_TAG_MAME, 0, 1); int g = driver_list::clone(*gdrv); if (g!=-1) gdrv = &driver_list::driver(g); else gdrv = NULL; } while (err && gdrv); if (err) mameinfo = 0; } } ParseClose(); } /* GAME INFORMATIONS */ snprintf(name, ARRAY_LENGTH(name), "\nGAME: %s\n", drv->name); strcat(buffer, name); snprintf(name, ARRAY_LENGTH(name), "%s", drv->description); strcat(buffer, name); snprintf(name, ARRAY_LENGTH(name), " (%s %s)\n\nCPU:\n", drv->manufacturer, drv->year); strcat(buffer, name); /* iterate over CPUs */ execute_interface_iterator iter(config.root_device()); device_execute_interface *cpu = iter.first(); while (cpu) { if (cpu->device().clock() >= 1000000) snprintf(name, ARRAY_LENGTH(name), "%s %d.%06d MHz\n", cpu->device().name(), cpu->device().clock() / 1000000, cpu->device().clock() % 1000000); else snprintf(name, ARRAY_LENGTH(name), "%s %d.%03d kHz\n", cpu->device().name(), cpu->device().clock() / 1000, cpu->device().clock() % 1000); strcat(buffer, name); cpu = iter.next(); } strcat(buffer, "\nSOUND:\n"); int has_sound = 0; /* iterate over sound chips */ sound_interface_iterator sounditer(config.root_device()); const device_sound_interface *sound = sounditer.first(); while(sound) { int clock = 0; int count = 0; device_type sound_type_; char tmpname[1024]; snprintf(tmpname, ARRAY_LENGTH(tmpname), "%s", sound->device().name()); sound_type_ = sound->device().type(); clock = sound->device().clock(); has_sound = 1; count = 1; sound = sounditer.next(); /* Matching chips at the same clock are aggregated */ while (sound && sound->device().type() == sound_type_ && sound->device().clock() == clock) { count++; sound = sounditer.next(); } if (count > 1) { snprintf(name, ARRAY_LENGTH(name), "%dx ",count); strcat(buffer, name); } strcat(buffer, tmpname); if (clock) { if (clock >= 1000000) snprintf(name, ARRAY_LENGTH(name), " %d.%06d MHz", clock / 1000000, clock % 1000000); else snprintf(name, ARRAY_LENGTH(name), " %d.%03d kHz", clock / 1000, clock % 1000); strcat(buffer, name); } strcat(buffer, "\n"); } if (has_sound) { speaker_device_iterator iter(config.root_device()); int channels = iter.count(); if(channels == 1) snprintf(name, ARRAY_LENGTH(name), "%d Channel\n",channels); else snprintf(name, ARRAY_LENGTH(name), "%dx Channels\n",channels); strcat(buffer, name); } strcat(buffer, "\nVIDEO:\n"); screen_device_iterator screeniter(config.root_device()); const screen_device *screen = screeniter.first(); if (screen == nullptr) strcat(buffer, "Screenless\n"); else if (screen->screen_type() == SCREEN_TYPE_VECTOR) strcat(buffer,"Vector\n"); else { for (; screen != nullptr; screen = screeniter.next()) { if (drv->flags & ORIENTATION_SWAP_XY) snprintf(name, ARRAY_LENGTH(name), "%d x %d (V)", screen->visible_area().height(), screen->visible_area().width()); else snprintf(name, ARRAY_LENGTH(name), "%d x %d (H)", screen->visible_area().width(), screen->visible_area().height()); strcat(buffer, name); snprintf(name, ARRAY_LENGTH(name), " %f Hz", ATTOSECONDS_TO_HZ(screen->refresh_attoseconds())); strcat(buffer, name); strcat(buffer, "\n"); } } strcat(buffer, "\nROM REGION:\n"); int g = driver_list::clone(*drv); if (g!=-1) parent = &driver_list::driver(g); device_iterator deviter(config.root_device()); for (device_t *device = deviter.first(); device; device = deviter.next()) { for (const rom_entry *region = rom_first_region(*device); region != nullptr; region = rom_next_region(region)) { for (const rom_entry *rom = rom_first_file(region); rom != nullptr; rom = rom_next_file(rom)) { hash_collection hashes(ROM_GETHASHDATA(rom)); if (g!=-1) { machine_config pconfig(*parent, MameUIGlobal()); device_iterator deviter(pconfig.root_device()); for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) for (const rom_entry *pregion = rom_first_region(*device); pregion != nullptr; pregion = rom_next_region(pregion)) for (const rom_entry *prom = rom_first_file(pregion); prom != nullptr; prom = rom_next_file(prom)) { hash_collection phashes(ROM_GETHASHDATA(prom)); if (hashes == phashes) break; } } snprintf(name, ARRAY_LENGTH(name), "%-16s \t", ROM_GETNAME(rom)); strcat(buffer, name); snprintf(name, ARRAY_LENGTH(name), "%09d \t", rom_file_size(rom)); strcat(buffer, name); snprintf(name, ARRAY_LENGTH(name), "%-10s", ROMREGION_GETTAG(region)); strcat(buffer, name); strcat(buffer, "\n"); } } } samples_device_iterator samplesiter(config.root_device()); for (samples_device *device = samplesiter.first(); device != nullptr; device = samplesiter.next()) { samples_iterator sampiter(*device); if (sampiter.altbasename() != nullptr) { snprintf(name, ARRAY_LENGTH(name), "\nSAMPLES (%s):\n", sampiter.altbasename()); strcat(buffer, name); } std::unordered_set<std::string> already_printed; for (const char *samplename = sampiter.first(); samplename != nullptr; samplename = sampiter.next()) { // filter out duplicates if (!already_printed.insert(samplename).second) continue; // output the sample name snprintf(name, ARRAY_LENGTH(name), "%s.wav\n", samplename); strcat(buffer, name); } } if (!is_bios) { int g = driver_list::clone(*drv); if (g!=-1) drv = &driver_list::driver(g); strcat(buffer, "\nORIGINAL:\n"); strcat(buffer, drv->description); strcat(buffer, "\n\nCLONES:\n"); for (int i = 0; i < driver_list::total(); i++) { if (!strcmp (drv->name, driver_list::driver(i).parent)) { strcat(buffer, driver_list::driver(i).description); strcat(buffer, "\n"); } } } strcat(buffer, "\n"); return (mameinfo == 0); }
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(); }
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 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; } } astring output; // opening tag if (!is_disk) output.cat("\t\t<rom"); else output.cat("\t\t<disk"); // add name, merge, bios, and size tags */ if (name != NULL && name[0] != 0) output.catprintf(" name=\"%s\"", xml_normalize_string(name)); if (merge_name != NULL) output.catprintf(" merge=\"%s\"", xml_normalize_string(merge_name)); if (bios_name[0] != 0) output.catprintf(" bios=\"%s\"", xml_normalize_string(bios_name)); if (!is_disk) output.catprintf(" 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 astring tempstr; output.catprintf(" %s", hashes.attribute_string(tempstr)); } else output.cat(" status=\"nodump\""); // append a region name output.catprintf(" region=\"%s\"", ROMREGION_GETTAG(region)); // for non-disk entries, print offset if (!is_disk) output.catprintf(" offset=\"%x\"", offset); // for disk entries, add the disk index else { output.catprintf(" index=\"%x\"", DISK_GETINDEX(rom)); output.catprintf(" writable=\"%s\"", DISK_ISREADONLY(rom) ? "no" : "yes"); } // add optional flag if (ROM_ISOPTIONAL(rom)) output.cat(" optional=\"yes\""); output.cat("/>\n"); fprintf(m_output, "%s", output.cstr()); } } }
int open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_entry *romp, chd_file &image_chd, const char *locationtag) { emu_file image_file(options.media_path(), OPEN_FLAG_READ); const rom_entry *region, *rom; file_error filerr; chd_error err; /* attempt to open the properly named file, scanning up through parent directories */ filerr = FILERR_NOT_FOUND; for (int searchdrv = driver_list::find(*gamedrv); searchdrv != -1 && filerr != FILERR_NONE; searchdrv = driver_list::clone(searchdrv)) filerr = common_process_file(options, driver_list::driver(searchdrv).name, ".chd", romp, image_file); if (filerr != FILERR_NONE) filerr = common_process_file(options, NULL, ".chd", romp, image_file); /* look for the disk in the locationtag too */ if (filerr != FILERR_NONE && locationtag != NULL) { // check if we are dealing with softwarelists. if so, locationtag // is actually a concatenation of: listname + setname + parentname // separated by '%' (parentname being present only for clones) astring tag1(locationtag), tag2, tag3, tag4, tag5; bool is_list = FALSE; bool has_parent = FALSE; int separator1 = tag1.chr(0, '%'); if (separator1 != -1) { is_list = TRUE; // we are loading through softlists, split the listname from the regiontag tag4.cpysubstr(tag1, separator1 + 1, tag1.len() - separator1 + 1); tag1.del(separator1, tag1.len() - separator1); tag1.cat(PATH_SEPARATOR); // check if we are loading a clone (if this is the case also tag1 have a separator '%') int separator2 = tag4.chr(0, '%'); if (separator2 != -1) { has_parent = TRUE; // we are loading a clone through softlists, split the setname from the parentname tag5.cpysubstr(tag4, separator2 + 1, tag4.len() - separator2 + 1); tag4.del(separator2, tag4.len() - separator2); } // prepare locations where we have to load from: list/parentname (if any) & list/clonename astring swlist(tag1.cstr()); tag2.cpy(swlist.cat(tag4)); if (has_parent) { swlist.cpy(tag1); tag3.cpy(swlist.cat(tag5)); } } if (tag5.chr(0, '%') != -1) fatalerror("We do not support clones of clones!\n"); // try to load from the available location(s): // - if we are not using lists, we have locationtag only; // - if we are using lists, we have: list/clonename, list/parentname, clonename, parentname if (!is_list) filerr = common_process_file(options, locationtag, ".chd", romp, image_file); else { // try to load from list/setname if ((filerr != FILERR_NONE) && (tag2.cstr() != NULL)) filerr = common_process_file(options, tag2.cstr(), ".chd", romp, image_file); // try to load from list/parentname (if any) if ((filerr != FILERR_NONE) && has_parent && (tag3.cstr() != NULL)) filerr = common_process_file(options, tag3.cstr(), ".chd", romp, image_file); // try to load from setname if ((filerr != FILERR_NONE) && (tag4.cstr() != NULL)) filerr = common_process_file(options, tag4.cstr(), ".chd", romp, image_file); // try to load from parentname (if any) if ((filerr != FILERR_NONE) && has_parent && (tag5.cstr() != NULL)) filerr = common_process_file(options, tag5.cstr(), ".chd", romp, image_file); // only for CHD we also try to load from list/ if ((filerr != FILERR_NONE) && (tag1.cstr() != NULL)) { tag1.del(tag1.len() - 1, 1); // remove the PATH_SEPARATOR filerr = common_process_file(options, tag1.cstr(), ".chd", romp, image_file); } } } /* did the file open succeed? */ if (filerr == FILERR_NONE) { astring fullpath(image_file.fullpath()); image_file.close(); /* try to open the CHD */ err = image_chd.open(fullpath); if (err == CHDERR_NONE) return err; } else err = CHDERR_FILE_NOT_FOUND; /* otherwise, look at our parents for a CHD with an identical checksum */ /* and try to open that */ hash_collection romphashes(ROM_GETHASHDATA(romp)); for (int drv = driver_list::find(*gamedrv); drv != -1; drv = driver_list::clone(drv)) { machine_config config(driver_list::driver(drv), options); device_iterator deviter(config.root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) for (region = rom_first_region(*device); region != NULL; region = rom_next_region(region)) if (ROMREGION_ISDISKDATA(region)) for (rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) /* look for a differing name but with the same hash data */ if (strcmp(ROM_GETNAME(romp), ROM_GETNAME(rom)) != 0 && romphashes == hash_collection(ROM_GETHASHDATA(rom))) { /* attempt to open the properly named file, scanning up through parent directories */ filerr = FILERR_NOT_FOUND; for (int searchdrv = drv; searchdrv != -1 && filerr != FILERR_NONE; searchdrv = driver_list::clone(searchdrv)) filerr = common_process_file(options, driver_list::driver(searchdrv).name, ".chd", rom, image_file); if (filerr != FILERR_NONE) filerr = common_process_file(options, NULL, ".chd", rom, image_file); /* did the file open succeed? */ if (filerr == FILERR_NONE) { astring fullpath(image_file.fullpath()); image_file.close(); /* try to open the CHD */ err = image_chd.open(fullpath); if (err == CHDERR_NONE) return err; } } } return err; }
static void print_game_rom(FILE *out, const game_driver *game, const machine_config *config) { const game_driver *clone_of = driver_get_clone(game); int rom_type; machine_config *pconfig = (clone_of != NULL) ? machine_config_alloc(clone_of->machine_config) : NULL; /* iterate over 3 different ROM "types": BIOS, ROMs, DISKs */ for (rom_type = 0; rom_type < 3; rom_type++) { const rom_source *source; const rom_entry *region; /* iterate over ROM sources: first the game, then any devices */ for (source = rom_first_source(game, config); source != NULL; source = rom_next_source(game, config, source)) for (region = rom_first_region(game, source); region != NULL; region = rom_next_region(region)) { int is_disk = ROMREGION_ISDISKDATA(region); const rom_entry *rom; /* disk regions only work for disks */ if ((is_disk && rom_type != 2) || (!is_disk && rom_type == 2)) continue; /* iterate through ROM entries */ for (rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) { int is_bios = ROM_GETBIOSFLAGS(rom); const char *name = ROM_GETNAME(rom); int offset = ROM_GETOFFSET(rom); const rom_entry *parent_rom = 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 */ if (!ROM_NOGOODDUMP(rom) && clone_of != NULL) { const rom_source *psource; const rom_entry *pregion, *prom; /* scan the clone_of ROM for a matching ROM entry */ for (psource = rom_first_source(clone_of, pconfig); psource != NULL; psource = rom_next_source(clone_of, pconfig, psource)) for (pregion = rom_first_region(clone_of, psource); pregion != NULL; pregion = rom_next_region(pregion)) for (prom = rom_first_file(pregion); prom != NULL; prom = rom_next_file(prom)) if (hash_data_is_equal(ROM_GETHASHDATA(rom), ROM_GETHASHDATA(prom), 0)) { parent_rom = prom; break; } } /* scan for a BIOS name */ bios_name[0] = 0; if (!is_disk && is_bios) { const rom_entry *brom; /* scan backwards through the ROM entries */ for (brom = rom - 1; brom != game->rom; brom--) if (ROMENTRY_ISSYSTEM_BIOS(brom)) { strcpy(bios_name, ROM_GETNAME(brom)); break; } } /* opening tag */ if (!is_disk) fprintf(out, "\t\t<rom"); else fprintf(out, "\t\t<disk"); /* add name, merge, bios, and size tags */ if (name != NULL && name[0] != 0) fprintf(out, " name=\"%s\"", xml_normalize_string(name)); if (parent_rom != NULL) fprintf(out, " merge=\"%s\"", xml_normalize_string(ROM_GETNAME(parent_rom))); if (bios_name[0] != 0) fprintf(out, " bios=\"%s\"", xml_normalize_string(bios_name)); if (!is_disk) fprintf(out, " size=\"%d\"", 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); } /* append a region name */ fprintf(out, " region=\"%s\"", ROMREGION_GETTAG(region)); /* add nodump/baddump flags */ if (hash_data_has_info(ROM_GETHASHDATA(rom), HASH_INFO_NO_DUMP)) fprintf(out, " status=\"nodump\""); if (hash_data_has_info(ROM_GETHASHDATA(rom), HASH_INFO_BAD_DUMP)) fprintf(out, " status=\"baddump\""); /* for non-disk entries, print offset */ if (!is_disk) fprintf(out, " offset=\"%x\"", offset); /* for disk entries, add the disk index */ else fprintf(out, " index=\"%x\"", DISK_GETINDEX(rom)); /* add optional flag */ if ((!is_disk && ROM_ISOPTIONAL(rom)) || (is_disk && DISK_ISOPTIONAL(rom))) fprintf(out, " optional=\"yes\""); fprintf(out, "/>\n"); } } } if (pconfig != NULL) machine_config_free(pconfig); }