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 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++; } }
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++; } }
/*------------------------------------------------- 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; }
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 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); }
bool device_image_interface::load_software(software_list_device &swlist, const char *swname, const rom_entry *start) { std::string locationtag, breakstr("%"); const rom_entry *region; bool retVal = FALSE; int warningcount = 0; for (region = start; region != nullptr; 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)) { osd_file::error filerr = osd_file::error::NOT_FOUND; UINT32 crc = 0; bool has_crc = hash_collection(ROM_GETHASHDATA(romp)).crc(crc); software_info *swinfo = swlist.find(swname); if (swinfo == nullptr) return false; UINT32 supported = swinfo->supported(); if (supported == SOFTWARE_SUPPORTED_PARTIAL) osd_printf_error("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist.list_name()); if (supported == SOFTWARE_SUPPORTED_NO) osd_printf_error("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist.list_name()); // attempt reading up the chain through the parents and create a locationtag std::string in the format // " swlist % clonename % parentname " // below, we have the code to split the elements and to create paths to load from while (swinfo != nullptr) { locationtag.append(swinfo->shortname()).append(breakstr); const char *parentname = swinfo->parentname(); swinfo = (parentname != nullptr) ? swlist.find(parentname) : nullptr; } // strip the final '%' locationtag.erase(locationtag.length() - 1, 1); // check if locationtag actually contains two locations separated by '%' // (i.e. check if we are dealing with a clone in softwarelist) std::string tag2, tag3, tag4(locationtag), tag5; int separator = tag4.find_first_of('%'); if (separator != -1) { // we are loading a clone through softlists, split the setname from the parentname tag5.assign(tag4.substr(separator + 1, tag4.length() - separator + 1)); tag4.erase(separator, tag4.length() - separator); } // prepare locations where we have to load from: list/parentname & list/clonename std::string tag1(swlist.list_name()); tag1.append(PATH_SEPARATOR); tag2.assign(tag1.append(tag4)); tag1.assign(swlist.list_name()); tag1.append(PATH_SEPARATOR); tag3.assign(tag1.append(tag5)); if (tag5.find_first_of('%') != -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 == nullptr) && (tag2.c_str() != nullptr)) m_mame_file = common_process_file(device().machine().options(), tag2.c_str(), has_crc, crc, romp, filerr); // try to load from list/parentname if ((m_mame_file == nullptr) && (tag3.c_str() != nullptr)) m_mame_file = common_process_file(device().machine().options(), tag3.c_str(), has_crc, crc, romp, filerr); // try to load from setname if ((m_mame_file == nullptr) && (tag4.c_str() != nullptr)) m_mame_file = common_process_file(device().machine().options(), tag4.c_str(), has_crc, crc, romp, filerr); // try to load from parentname if ((m_mame_file == nullptr) && (tag5.c_str() != nullptr)) m_mame_file = common_process_file(device().machine().options(), tag5.c_str(), has_crc, crc, romp, filerr); warningcount += verify_length_and_hash(m_mame_file.get(),ROM_GETNAME(romp),ROM_GETLENGTH(romp),hash_collection(ROM_GETHASHDATA(romp))); if (filerr == osd_file::error::NONE) filerr = util::core_file::open_proxy(*m_mame_file, m_file); if (filerr == osd_file::error::NONE) retVal = TRUE; break; // load first item for start } romp++; /* something else; skip */ } } if (warningcount > 0) { osd_printf_error("WARNING: the software item might not run correctly.\n"); } return retVal; }