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 != NULL; 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 = NULL; 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 != NULL && (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()); }
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)++; } } } }
void rom_load_manager::fill_rom_data(const rom_entry *romp) { UINT32 numbytes = ROM_GETLENGTH(romp); int skip = ROM_GETSKIPCOUNT(romp); UINT8 *base = m_region->base() + ROM_GETOFFSET(romp); /* make sure we fill within the region space */ if (ROM_GETOFFSET(romp) + numbytes > m_region->bytes()) fatalerror("Error in RomModule definition: FILL out of memory region space\n"); /* make sure the length was valid */ if (numbytes == 0) fatalerror("Error in RomModule definition: FILL has an invalid length\n"); /* fill the data (filling value is stored in place of the hashdata) */ if(skip != 0) { for (int i = 0; i < numbytes; i+= skip + 1) base[i] = (FPTR)ROM_GETHASHDATA(romp) & 0xff; } else memset(base, (FPTR)ROM_GETHASHDATA(romp) & 0xff, numbytes); }
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"); } } }
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 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; }
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 void fill_rom_data(romload_private *romdata, const rom_entry *romp) { UINT32 numbytes = ROM_GETLENGTH(romp); UINT8 *base = romdata->region->base() + ROM_GETOFFSET(romp); /* make sure we fill within the region space */ if (ROM_GETOFFSET(romp) + numbytes > romdata->region->bytes()) fatalerror("Error in RomModule definition: FILL out of memory region space\n"); /* make sure the length was valid */ if (numbytes == 0) fatalerror("Error in RomModule definition: FILL has an invalid length\n"); /* fill the data (filling value is stored in place of the hashdata) */ memset(base, (FPTR)ROM_GETHASHDATA(romp) & 0xff, numbytes); }
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; }
STDMETHODIMP CRom::Audit(VARIANT_BOOL fStrict) { int err; char szHash[256]; lstrcpy(szHash, fStrict?"":ROM_GETHASHDATA(m_rom)); /* obtain CRC-32 and length of ROM file */ const struct GameDriver *drv = m_gamedrv; do { err = mame_fchecksum(drv->name, m_pszName, (unsigned int*) &m_dwLength, szHash); drv = drv->clone_of; } while (err && drv); if (err) { if (!m_dwChecksum) /* not found but it's not good anyway */ m_dwState = AUD_NOT_AVAILABLE; else /* not found */ m_dwState = AUD_ROM_NOT_FOUND; } else { m_dwChecksum = GetChecksumFromHash(szHash); /* all cases below assume the ROM was at least found */ if (m_dwExpLength != m_dwLength) m_dwState = AUD_LENGTH_MISMATCH; else if (m_dwExpChecksum != m_dwChecksum) { if (!m_dwExpChecksum) m_dwState = AUD_ROM_NEED_DUMP; /* new case - found but not known to be dumped */ else if (m_dwChecksum == BADCRC(m_dwExpChecksum)) m_dwState = AUD_ROM_NEED_REDUMP; else m_dwState = AUD_BAD_CHECKSUM; } else m_dwState = AUD_ROM_GOOD; } return S_OK; }
void info_xml_creator::output_bios() { // skip if no ROMs if (m_drivlist.driver().rom == NULL) return; // iterate over ROM entries and look for BIOSes for (const rom_entry *rom = m_drivlist.driver().rom; !ROMENTRY_ISEND(rom); rom++) if (ROMENTRY_ISSYSTEM_BIOS(rom)) { // output extracted name and descriptions fprintf(m_output, "\t\t<biosset"); fprintf(m_output, " name=\"%s\"", xml_normalize_string(ROM_GETNAME(rom))); fprintf(m_output, " description=\"%s\"", xml_normalize_string(ROM_GETHASHDATA(rom))); if (ROM_GETBIOSFLAGS(rom) == 1) fprintf(m_output, " default=\"yes\""); fprintf(m_output, "/>\n"); } }
static int open_rom_file(struct rom_load_data *romdata, const struct RomModule *romp) { const struct GameDriver *drv; ++romdata->romsloaded; /* update status display */ if (osd_display_loading_rom_message(ROM_GETNAME(romp), romdata)) return 0; /* Attempt reading up the chain through the parents. It automatically also attempts any kind of load by checksum supported by the archives. */ romdata->file = NULL; for (drv = Machine->gamedrv; !romdata->file && drv; drv = drv->clone_of) if (drv->name && *drv->name) romdata->file = mame_fopen_rom(drv->name, ROM_GETNAME(romp), ROM_GETHASHDATA(romp)); /* return the result */ return (romdata->file != NULL); }
static int copy_rom_data(struct rom_load_data *romdata, const struct RomModule *romp) { UINT8 *base = romdata->regionbase + ROM_GETOFFSET(romp); int srcregion = ROM_GETFLAGS(romp) >> 24; UINT32 numbytes = ROM_GETLENGTH(romp); UINT32 srcoffs = (UINT32)ROM_GETHASHDATA(romp); /* srcoffset in place of hashdata */ UINT8 *srcbase; /* make sure we copy within the region space */ if (ROM_GETOFFSET(romp) + numbytes > romdata->regionlength) { printf("Error in RomModule definition: COPY out of target memory region space\n"); return 0; } /* make sure the length was valid */ if (numbytes == 0) { printf("Error in RomModule definition: COPY has an invalid length\n"); return 0; } /* make sure the source was valid */ srcbase = memory_region(srcregion); if (!srcbase) { printf("Error in RomModule definition: COPY from an invalid region\n"); return 0; } /* make sure we find within the region space */ if (srcoffs + numbytes > memory_region_length(srcregion)) { printf("Error in RomModule definition: COPY out of source memory region space\n"); return 0; } /* fill the data */ memcpy(base, srcbase + srcoffs, numbytes); return 1; }
/*------------------------------------------------- load_software - software image loading -------------------------------------------------*/ bool legacy_image_device_base::load_software(char *swlist, char *swname, rom_entry *start) { const rom_entry *region; astring regiontag; bool retVal = FALSE; for (region = start; region != NULL; region = rom_next_region(region)) { /* loop until we hit the end of this region */ const rom_entry *romp = region + 1; while (!ROMENTRY_ISREGIONEND(romp)) { /* handle files */ if (ROMENTRY_ISFILE(romp)) { UINT32 crc = 0; UINT8 crcbytes[4]; file_error filerr; bool has_crc = hash_data_extract_binary_checksum(ROM_GETHASHDATA(romp), HASH_CRC, crcbytes); if (has_crc) crc = (crcbytes[0] << 24) | (crcbytes[1] << 16) | (crcbytes[2] << 8) | crcbytes[3]; astring fname(swlist, PATH_SEPARATOR, swname, PATH_SEPARATOR, ROM_GETNAME(romp)); if (has_crc) filerr = mame_fopen_crc(libretro_content_directory, fname, crc, OPEN_FLAG_READ, &m_mame_file); else filerr = mame_fopen(libretro_content_directory, fname, OPEN_FLAG_READ, &m_mame_file); if (filerr == FILERR_NONE) { m_file = mame_core_file(m_mame_file); retVal = TRUE; } break; // load first item for start } romp++; /* something else; skip */ } } return retVal; }
void ui_menu_bios_selection::populate() { /* cycle through all devices for this system */ device_iterator deviter(machine().root_device()); for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) { if (device->rom_region()) { const char *val = "default"; for (const rom_entry *rom = device->rom_region(); !ROMENTRY_ISEND(rom); rom++) { if (ROMENTRY_ISSYSTEM_BIOS(rom) && ROM_GETBIOSFLAGS(rom)==device->system_bios()) { val = ROM_GETHASHDATA(rom); } } item_append(strcmp(device->tag(),":")==0 ? "driver" : device->tag()+1, val, MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW, (void *)device); } } item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr); item_append(_("Reset"), nullptr, 0, (void *)1); }
void rom_load_manager::handle_missing_file(const rom_entry *romp, std::string tried_file_names, chd_error chderr) { if(tried_file_names.length() != 0) tried_file_names = " (tried in " + tried_file_names + ")"; std::string name(ROM_GETNAME(romp)); bool is_chd = (chderr != CHDERR_NONE); if (is_chd) name += ".chd"; bool is_chd_error = (is_chd && chderr != CHDERR_FILE_NOT_FOUND); if (is_chd_error) strcatprintf(m_errorstring, "%s CHD ERROR: %s\n", name.c_str(), chd_file::error_string(chderr)); /* optional files are okay */ if (ROM_ISOPTIONAL(romp)) { if (!is_chd_error) strcatprintf(m_errorstring, "OPTIONAL %s NOT FOUND%s\n", name.c_str(), tried_file_names.c_str()); m_warnings++; } /* no good dumps are okay */ else if (hash_collection(ROM_GETHASHDATA(romp)).flag(hash_collection::FLAG_NO_DUMP)) { if (!is_chd_error) strcatprintf(m_errorstring, "%s NOT FOUND (NO GOOD DUMP KNOWN)%s\n", name.c_str(), tried_file_names.c_str()); m_knownbad++; } /* anything else is bad */ else { if (!is_chd_error) strcatprintf(m_errorstring, "%s NOT FOUND%s\n", name.c_str(), tried_file_names.c_str()); m_errors++; } }
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; }
void ui_menu_bios_selection::populate() { /* cycle through all devices for this system */ for (device_t &device : device_iterator(machine().root_device())) { if (device.rom_region()) { const char *val = "default"; for (const rom_entry *rom = device.rom_region(); !ROMENTRY_ISEND(rom); rom++) { if (ROMENTRY_ISSYSTEM_BIOS(rom) && ROM_GETBIOSFLAGS(rom) == device.system_bios()) { val = ROM_GETHASHDATA(rom); } } item_append(device.owner() == nullptr ? "driver" : device.tag()+1, val, MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW, (void *)&device); } } item_append(ui_menu_item_type::SEPARATOR); item_append(_("Reset"), nullptr, 0, (void *)1); }
static void handle_missing_file(romload_private *romdata, const rom_entry *romp, astring tried_file_names, chd_error chderr) { if(tried_file_names.len() != 0) tried_file_names = " (tried in " + tried_file_names + ")"; astring name(ROM_GETNAME(romp)); bool is_chd = (chderr != CHDERR_NONE); if (is_chd) name += ".chd"; bool is_chd_error = (is_chd && chderr != CHDERR_FILE_NOT_FOUND); if (is_chd_error) romdata->errorstring.catprintf("%s CHD ERROR: %s\n", name.cstr(), chd_file::error_string(chderr)); /* optional files are okay */ if (ROM_ISOPTIONAL(romp)) { if (!is_chd_error) romdata->errorstring.catprintf("OPTIONAL %s NOT FOUND%s\n", name.cstr(), tried_file_names.cstr()); romdata->warnings++; } /* no good dumps are okay */ else if (hash_collection(ROM_GETHASHDATA(romp)).flag(hash_collection::FLAG_NO_DUMP)) { if (!is_chd_error) romdata->errorstring.catprintf("%s NOT FOUND (NO GOOD DUMP KNOWN)%s\n", name.cstr(), tried_file_names.cstr()); romdata->knownbad++; } /* anything else is bad */ else { if (!is_chd_error) romdata->errorstring.catprintf("%s NOT FOUND%s\n", name.cstr(), tried_file_names.cstr()); romdata->errors++; } }
void ui_menu_machine_configure::setup_bios() { if (m_drv->rom == nullptr) return; std::string specbios(m_opts.bios()); std::string default_name; for (const rom_entry *rom = m_drv->rom; !ROMENTRY_ISEND(rom); ++rom) if (ROMENTRY_ISDEFAULT_BIOS(rom)) default_name = ROM_GETNAME(rom); int bios_count = 0; for (const rom_entry *rom = m_drv->rom; !ROMENTRY_ISEND(rom); ++rom) { if (ROMENTRY_ISSYSTEM_BIOS(rom)) { std::string name(ROM_GETHASHDATA(rom)); std::string biosname(ROM_GETNAME(rom)); int bios_flags = ROM_GETBIOSFLAGS(rom); std::string bios_number = std::to_string(bios_flags - 1); // check biosnumber and name if (bios_number == specbios || biosname == specbios) m_curbios = bios_count; if (biosname == default_name) { name.append(_(" (default)")); if (specbios == "default") m_curbios = bios_count; } m_bios.emplace_back(name, bios_flags - 1); bios_count++; } } }
static void handle_missing_file(rom_load_data *romdata, const rom_entry *romp) { /* optional files are okay */ if (ROM_ISOPTIONAL(romp)) { romdata->errorstring.catprintf("OPTIONAL %s NOT FOUND\n", ROM_GETNAME(romp)); romdata->warnings++; } /* no good dumps are okay */ else if (hash_collection(ROM_GETHASHDATA(romp)).flag(hash_collection::FLAG_NO_DUMP)) { romdata->errorstring.catprintf("%s NOT FOUND (NO GOOD DUMP KNOWN)\n", ROM_GETNAME(romp)); romdata->knownbad++; } /* anything else is bad */ else { romdata->errorstring.catprintf("%s NOT FOUND\n", ROM_GETNAME(romp)); romdata->errors++; } }
static int fill_rom_data(struct rom_load_data *romdata, const struct RomModule *romp) { UINT32 numbytes = ROM_GETLENGTH(romp); UINT8 *base = romdata->regionbase + ROM_GETOFFSET(romp); /* make sure we fill within the region space */ if (ROM_GETOFFSET(romp) + numbytes > romdata->regionlength) { printf("Error in RomModule definition: FILL out of memory region space\n"); return 0; } /* make sure the length was valid */ if (numbytes == 0) { printf("Error in RomModule definition: FILL has an invalid length\n"); return 0; } /* fill the data (filling value is stored in place of the hashdata) */ memset(base, (UINT32)ROM_GETHASHDATA(romp) & 0xff, numbytes); return 1; }
static void print_game_bios(FILE *out, const game_driver *game) { const rom_entry *rom; /* skip if no ROMs */ if (game->rom == NULL) return; /* iterate over ROM entries and look for BIOSes */ for (rom = game->rom; !ROMENTRY_ISEND(rom); rom++) if (ROMENTRY_ISSYSTEM_BIOS(rom)) { const char *name = ROM_GETNAME(rom); const char *description = ROM_GETHASHDATA(rom); /* output extracted name and descriptions */ fprintf(out, "\t\t<biosset"); fprintf(out, " name=\"%s\"", xml_normalize_string(name)); fprintf(out, " description=\"%s\"", xml_normalize_string(description)); if (ROM_GETBIOSFLAGS(rom) == 1) fprintf(out, " default=\"yes\""); fprintf(out, "/>\n"); } }
/*------------------------------------------------- load_software - software image loading -------------------------------------------------*/ bool device_image_interface::load_software(char *swlist, char *swname, rom_entry *start) { astring locationtag, breakstr("%"); const rom_entry *region; astring regiontag; bool retVal = FALSE; for (region = start; region != NULL; region = rom_next_region(region)) { /* loop until we hit the end of this region */ const rom_entry *romp = region + 1; while (!ROMENTRY_ISREGIONEND(romp)) { /* handle files */ if (ROMENTRY_ISFILE(romp)) { file_error filerr = FILERR_NOT_FOUND; UINT32 crc = 0; bool has_crc = hash_collection(ROM_GETHASHDATA(romp)).crc(crc); // attempt reading up the chain through the parents and create a locationtag astring in the format // " swlist % clonename % parentname " // below, we have 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) { 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); } if (software_get_support(device().machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_PARTIAL) mame_printf_error("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist); if (software_get_support(device().machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_NO) mame_printf_error("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist); // check if locationtag actually contains two locations separated by '%' // (i.e. check if we are dealing with a clone in softwarelist) astring tag2, tag3, tag4(locationtag), tag5; int separator = tag4.chr(0, '%'); if (separator != -1) { // we are loading a clone through softlists, split the setname from the parentname tag5.cpysubstr(tag4, separator + 1, tag4.len() - separator + 1); tag4.del(separator, tag4.len() - separator); } // prepare locations where we have to load from: list/parentname & list/clonename astring tag1(swlist); tag1.cat(PATH_SEPARATOR); tag2.cpy(tag1.cat(tag4)); tag1.cpy(swlist); tag1.cat(PATH_SEPARATOR); tag3.cpy(tag1.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 regiontag only; // - if we are using lists, we have: list/clonename, list/parentname, clonename, parentname // try to load from list/setname if ((m_mame_file == NULL) && (tag2.cstr() != NULL)) filerr = common_process_file(device().machine().options(), tag2.cstr(), has_crc, crc, romp, &m_mame_file); // try to load from list/parentname if ((m_mame_file == NULL) && (tag3.cstr() != NULL)) filerr = common_process_file(device().machine().options(), tag3.cstr(), has_crc, crc, romp, &m_mame_file); // try to load from setname if ((m_mame_file == NULL) && (tag4.cstr() != NULL)) filerr = common_process_file(device().machine().options(), tag4.cstr(), has_crc, crc, romp, &m_mame_file); // try to load from parentname if ((m_mame_file == NULL) && (tag5.cstr() != NULL)) filerr = common_process_file(device().machine().options(), tag5.cstr(), has_crc, crc, romp, &m_mame_file); if (filerr == FILERR_NONE) { m_file = *m_mame_file; retVal = TRUE; } break; // load first item for start } romp++; /* something else; skip */ } } return retVal; }
void menu_device_config::populate() { std::ostringstream str; device_t *dev; util::stream_format(str, "[This option is%s currently mounted in the running system]\n\n", m_mounted ? "" : " NOT"); util::stream_format(str, "Option: %s\n", m_option->name()); dev = const_cast<machine_config &>(machine().config()).device_add(&machine().config().root_device(), m_option->name(), m_option->devtype(), 0); util::stream_format(str, "Device: %s\n", dev->name()); if (!m_mounted) str << "\nIf you select this option, the following items will be enabled:\n"; else str << "\nThe selected option enables the following items:\n"; // loop over all CPUs execute_interface_iterator execiter(*dev); if (execiter.count() > 0) { str << "* CPU:\n"; std::unordered_set<std::string> exectags; for (device_execute_interface &exec : execiter) { if (!exectags.insert(exec.device().tag()).second) continue; // get cpu specific clock that takes internal multiplier/dividers into account int clock = exec.device().clock(); // count how many identical CPUs we have int count = 1; const char *name = exec.device().name(); for (device_execute_interface &scan : execiter) { if (exec.device().type() == scan.device().type() && strcmp(name, scan.device().name()) == 0 && exec.device().clock() == scan.device().clock()) if (exectags.insert(scan.device().tag()).second) count++; } // if more than one, prepend a #x in front of the CPU name if (count > 1) util::stream_format(str, " %d" UTF8_MULTIPLY, count); else str << " "; str << name; // display clock in kHz or MHz if (clock >= 1000000) util::stream_format(str, " %d.%06d" UTF8_NBSP "MHz\n", clock / 1000000, clock % 1000000); else util::stream_format(str, " %d.%03d" UTF8_NBSP "kHz\n", clock / 1000, clock % 1000); } } // display screen information screen_device_iterator scriter(*dev); if (scriter.count() > 0) { str << "* Video:\n"; for (screen_device &screen : scriter) { util::stream_format(str, " Screen '%s': ", screen.tag()); if (screen.screen_type() == SCREEN_TYPE_VECTOR) str << "Vector\n"; else { const rectangle &visarea = screen.visible_area(); util::stream_format(str, "%d " UTF8_MULTIPLY " %d (%s) %f" UTF8_NBSP "Hz\n", visarea.width(), visarea.height(), (machine().system().flags & ORIENTATION_SWAP_XY) ? "V" : "H", ATTOSECONDS_TO_HZ(screen.frame_period().attoseconds())); } } } // loop over all sound chips sound_interface_iterator snditer(*dev); if (snditer.count() > 0) { str << "* Sound:\n"; std::unordered_set<std::string> soundtags; for (device_sound_interface &sound : snditer) { if (!soundtags.insert(sound.device().tag()).second) continue; // count how many identical sound chips we have int count = 1; for (device_sound_interface &scan : snditer) { if (sound.device().type() == scan.device().type() && sound.device().clock() == scan.device().clock()) if (soundtags.insert(scan.device().tag()).second) count++; } // if more than one, prepend a #x in front of the CPU name if (count > 1) util::stream_format(str," %d" UTF8_MULTIPLY, count); else str << " "; str << sound.device().name(); // display clock in kHz or MHz int clock = sound.device().clock(); if (clock >= 1000000) util::stream_format(str," %d.%06d" UTF8_NBSP "MHz\n", clock / 1000000, clock % 1000000); else if (clock != 0) util::stream_format(str," %d.%03d" UTF8_NBSP "kHz\n", clock / 1000, clock % 1000); else str << '\n'; } } // scan for BIOS settings int bios = 0; if (dev->rom_region()) { std::string bios_str; // first loop through roms in search of default bios (shortname) for (const rom_entry &rom : dev->rom_region_vector()) if (ROMENTRY_ISDEFAULT_BIOS(&rom)) bios_str.assign(ROM_GETNAME(&rom)); // then loop again to count bios options and to get the default bios complete name for (const rom_entry &rom : dev->rom_region_vector()) { if (ROMENTRY_ISSYSTEM_BIOS(&rom)) { bios++; if (bios_str.compare(ROM_GETNAME(&rom))==0) bios_str.assign(ROM_GETHASHDATA(&rom)); } } if (bios) util::stream_format(str, "* BIOS settings:\n %d options [default: %s]\n", bios, bios_str.c_str()); } int input = 0, input_mj = 0, input_hana = 0, input_gamble = 0, input_analog = 0, input_adjust = 0; int input_keypad = 0, input_keyboard = 0, dips = 0, confs = 0; std::string errors; std::ostringstream dips_opt, confs_opt; ioport_list portlist; for (device_t &iptdev : device_iterator(*dev)) portlist.append(iptdev, errors); // check if the device adds inputs to the system for (auto &port : portlist) for (ioport_field &field : port.second->fields()) { if (field.type() >= IPT_MAHJONG_FIRST && field.type() < IPT_MAHJONG_LAST) input_mj++; else if (field.type() >= IPT_HANAFUDA_FIRST && field.type() < IPT_HANAFUDA_LAST) input_hana++; else if (field.type() >= IPT_GAMBLING_FIRST && field.type() < IPT_GAMBLING_LAST) input_gamble++; else if (field.type() >= IPT_ANALOG_FIRST && field.type() < IPT_ANALOG_LAST) input_analog++; else if (field.type() == IPT_ADJUSTER) input_adjust++; else if (field.type() == IPT_KEYPAD) input_keypad++; else if (field.type() == IPT_KEYBOARD) input_keyboard++; else if (field.type() >= IPT_START1 && field.type() < IPT_UI_FIRST) input++; else if (field.type() == IPT_DIPSWITCH) { dips++; dips_opt << " " << field.name(); for (ioport_setting &setting : field.settings()) { if (setting.value() == field.defvalue()) { util::stream_format(dips_opt, " [default: %s]\n", setting.name()); break; } } } else if (field.type() == IPT_CONFIG) { confs++; confs_opt << " " << field.name(); for (ioport_setting &setting : field.settings()) { if (setting.value() == field.defvalue()) { util::stream_format(confs_opt, " [default: %s]\n", setting.name()); break; } } } } if (dips) str << "* Dispwitch settings:\n" << dips_opt.str(); if (confs) str << "* Configuration settings:\n" << confs_opt.str(); if (input + input_mj + input_hana + input_gamble + input_analog + input_adjust + input_keypad + input_keyboard) str << "* Input device(s):\n"; if (input) util::stream_format(str, " User inputs [%d inputs]\n", input); if (input_mj) util::stream_format(str, " Mahjong inputs [%d inputs]\n", input_mj); if (input_hana) util::stream_format(str, " Hanafuda inputs [%d inputs]\n", input_hana); if (input_gamble) util::stream_format(str, " Gambling inputs [%d inputs]\n", input_gamble); if (input_analog) util::stream_format(str, " Analog inputs [%d inputs]\n", input_analog); if (input_adjust) util::stream_format(str, " Adjuster inputs [%d inputs]\n", input_adjust); if (input_keypad) util::stream_format(str, " Keypad inputs [%d inputs]\n", input_keypad); if (input_keyboard) util::stream_format(str, " Keyboard inputs [%d inputs]\n", input_keyboard); image_interface_iterator imgiter(*dev); if (imgiter.count() > 0) { str << "* Media Options:\n"; for (const device_image_interface &imagedev : imgiter) util::stream_format(str, " %s [tag: %s]\n", imagedev.image_type_name(), imagedev.device().tag()); } slot_interface_iterator slotiter(*dev); if (slotiter.count() > 0) { str << "* Slot Options:\n"; for (const device_slot_interface &slot : slotiter) util::stream_format(str, " %s [default: %s]\n", slot.device().tag(), slot.default_option() ? slot.default_option() : "----"); } if ((execiter.count() + scriter.count() + snditer.count() + imgiter.count() + slotiter.count() + bios + dips + confs + input + input_mj + input_hana + input_gamble + input_analog + input_adjust + input_keypad + input_keyboard) == 0) str << "[None]\n"; const_cast<machine_config &>(machine().config()).device_remove(&machine().config().root_device(), m_option->name()); item_append(str.str(), "", FLAG_MULTILINE, nullptr); }
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 process_rom_entries(romload_private *romdata, const char *regiontag, const rom_entry *parent_region, const rom_entry *romp, device_t *device, bool from_list) { UINT32 lastflags = 0; /* loop until we hit the end of this region */ while (!ROMENTRY_ISREGIONEND(romp)) { /* if this is a continue entry, it's invalid */ if (ROMENTRY_ISCONTINUE(romp)) fatalerror("Error in RomModule definition: ROM_CONTINUE not preceded by ROM_LOAD\n"); /* if this is an ignore entry, it's invalid */ if (ROMENTRY_ISIGNORE(romp)) fatalerror("Error in RomModule definition: ROM_IGNORE not preceded by ROM_LOAD\n"); /* if this is a reload entry, it's invalid */ if (ROMENTRY_ISRELOAD(romp)) fatalerror("Error in RomModule definition: ROM_RELOAD not preceded by ROM_LOAD\n"); /* handle fills */ if (ROMENTRY_ISFILL(romp)) fill_rom_data(romdata, romp++); /* handle copies */ else if (ROMENTRY_ISCOPY(romp)) copy_rom_data(romdata, romp++); /* handle files */ else if (ROMENTRY_ISFILE(romp)) { int irrelevantbios = (ROM_GETBIOSFLAGS(romp) != 0 && ROM_GETBIOSFLAGS(romp) != device->system_bios()); const rom_entry *baserom = romp; int explength = 0; /* open the file if it is a non-BIOS or matches the current BIOS */ LOG(("Opening ROM file: %s\n", ROM_GETNAME(romp))); astring tried_file_names; if (!irrelevantbios && !open_rom_file(romdata, regiontag, romp, tried_file_names, from_list)) handle_missing_file(romdata, romp, tried_file_names, CHDERR_NONE); /* loop until we run out of reloads */ do { /* loop until we run out of continues/ignores */ do { rom_entry modified_romp = *romp++; //int readresult; /* handle flag inheritance */ if (!ROM_INHERITSFLAGS(&modified_romp)) lastflags = modified_romp._flags; else modified_romp._flags = (modified_romp._flags & ~ROM_INHERITEDFLAGS) | lastflags; explength += ROM_GETLENGTH(&modified_romp); /* attempt to read using the modified entry */ if (!ROMENTRY_ISIGNORE(&modified_romp) && !irrelevantbios) /*readresult = */read_rom_data(romdata, parent_region, &modified_romp); } while (ROMENTRY_ISCONTINUE(romp) || ROMENTRY_ISIGNORE(romp)); /* if this was the first use of this file, verify the length and CRC */ if (baserom) { LOG(("Verifying length (%X) and checksums\n", explength)); verify_length_and_hash(romdata, ROM_GETNAME(baserom), explength, hash_collection(ROM_GETHASHDATA(baserom))); LOG(("Verify finished\n")); } /* reseek to the start and clear the baserom so we don't reverify */ if (romdata->file != NULL) romdata->file->seek(0, SEEK_SET); baserom = NULL; explength = 0; } while (ROMENTRY_ISRELOAD(romp)); /* close the file */ if (romdata->file != NULL) { LOG(("Closing ROM file\n")); global_free(romdata->file); romdata->file = NULL; } } else { romp++; /* something else; skip */ } } }
static void process_disk_entries(romload_private *romdata, const char *regiontag, const rom_entry *parent_region, const rom_entry *romp, const char *locationtag) { /* loop until we hit the end of this region */ for ( ; !ROMENTRY_ISREGIONEND(romp); romp++) { /* handle files */ if (ROMENTRY_ISFILE(romp)) { open_chd *chd = global_alloc(open_chd(regiontag)); hash_collection hashes(ROM_GETHASHDATA(romp)); chd_error err; /* make the filename of the source */ astring filename(ROM_GETNAME(romp), ".chd"); /* first open the source drive */ LOG(("Opening disk image: %s\n", filename.cstr())); err = chd_error(open_disk_image(romdata->machine().options(), &romdata->machine().system(), romp, chd->orig_chd(), locationtag)); if (err != CHDERR_NONE) { handle_missing_file(romdata, romp, astring(), err); global_free(chd); continue; } /* get the header and extract the SHA1 */ hash_collection acthashes; acthashes.add_sha1(chd->orig_chd().sha1()); /* verify the hash */ if (hashes != acthashes) { romdata->errorstring.catprintf("%s WRONG CHECKSUMS:\n", filename.cstr()); dump_wrong_and_correct_checksums(romdata, hashes, acthashes); romdata->warnings++; } else if (hashes.flag(hash_collection::FLAG_BAD_DUMP)) { romdata->errorstring.catprintf("%s CHD NEEDS REDUMP\n", filename.cstr()); romdata->knownbad++; } /* if not read-only, make the diff file */ if (!DISK_ISREADONLY(romp)) { /* try to open or create the diff */ err = open_disk_diff(romdata->machine().options(), romp, chd->orig_chd(), chd->diff_chd()); if (err != CHDERR_NONE) { romdata->errorstring.catprintf("%s DIFF CHD ERROR: %s\n", filename.cstr(), chd_file::error_string(err)); romdata->errors++; global_free(chd); continue; } } /* we're okay, add to the list of disks */ LOG(("Assigning to handle %d\n", DISK_GETINDEX(romp))); romdata->machine().romload_data->chd_list.append(*chd); } } }
static int open_rom_file(romload_private *romdata, const char *regiontag, const rom_entry *romp, astring &tried_file_names, bool from_list) { file_error filerr = FILERR_NOT_FOUND; UINT32 romsize = rom_file_size(romp); tried_file_names = ""; /* update status display */ display_loading_rom_message(romdata, ROM_GETNAME(romp), from_list); /* extract CRC to use for searching */ UINT32 crc = 0; bool has_crc = hash_collection(ROM_GETHASHDATA(romp)).crc(crc); /* attempt reading up the chain through the parents. It automatically also attempts any kind of load by checksum supported by the archives. */ romdata->file = NULL; for (int drv = driver_list::find(romdata->machine().system()); romdata->file == NULL && drv != -1; drv = driver_list::clone(drv)) { if(tried_file_names.len() != 0) tried_file_names += " "; tried_file_names += driver_list::driver(drv).name; filerr = common_process_file(romdata->machine().options(), driver_list::driver(drv).name, has_crc, crc, romp, &romdata->file); } /* if the region is load by name, load the ROM from there */ if (romdata->file == NULL && regiontag != 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(regiontag), 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 & 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 regiontag only; // - if we are using lists, we have: list/clonename, list/parentname, clonename, parentname if (!is_list) { tried_file_names += " " + tag1; filerr = common_process_file(romdata->machine().options(), tag1.cstr(), has_crc, crc, romp, &romdata->file); } else { // try to load from list/setname if ((romdata->file == NULL) && (tag2.cstr() != NULL)) { tried_file_names += " " + tag2; filerr = common_process_file(romdata->machine().options(), tag2.cstr(), has_crc, crc, romp, &romdata->file); } // try to load from list/parentname if ((romdata->file == NULL) && has_parent && (tag3.cstr() != NULL)) { tried_file_names += " " + tag3; filerr = common_process_file(romdata->machine().options(), tag3.cstr(), has_crc, crc, romp, &romdata->file); } // try to load from setname if ((romdata->file == NULL) && (tag4.cstr() != NULL)) { tried_file_names += " " + tag4; filerr = common_process_file(romdata->machine().options(), tag4.cstr(), has_crc, crc, romp, &romdata->file); } // try to load from parentname if ((romdata->file == NULL) && has_parent && (tag5.cstr() != NULL)) { tried_file_names += " " + tag5; filerr = common_process_file(romdata->machine().options(), tag5.cstr(), has_crc, crc, romp, &romdata->file); } } } /* update counters */ romdata->romsloaded++; romdata->romsloadedsize += romsize; /* return the result */ return (filerr == FILERR_NONE); }