static int verify_length_and_hash(emu_file *file, const char *name, UINT32 explength, const util::hash_collection &hashes) { int retVal = 0; if (file==nullptr) return 0; // verify length UINT32 actlength = file->size(); if (explength != actlength) { osd_printf_error("%s WRONG LENGTH (expected: %d found: %d)\n", name, explength, actlength); retVal++; } // If there is no good dump known, write it util::hash_collection &acthashes = file->hashes(hashes.hash_types().c_str()); if (hashes.flag(util::hash_collection::FLAG_NO_DUMP)) { osd_printf_error("%s NO GOOD DUMP KNOWN\n", name); } // verify checksums else if (hashes != acthashes) { // otherwise, it's just bad osd_printf_error("%s WRONG CHECKSUMS:\n", name); dump_wrong_and_correct_checksums(hashes, acthashes); retVal++; } // If it matches, but it is actually a bad dump, write it else if (hashes.flag(util::hash_collection::FLAG_BAD_DUMP)) { osd_printf_error("%s NEEDS REDUMP\n",name); } return retVal; }
void a78_partialhash(util::hash_collection &dest, const unsigned char *data, unsigned long length, const char *functions) { if (length <= 128) return; dest.compute(&data[128], length - 128, functions); }
void device_image_interface::device_compute_hash(util::hash_collection &hashes, const void *data, size_t length, const char *types) const { /* retrieve the partial hash func */ device_image_partialhash_func partialhash = get_partial_hash(); /* compute the hash */ if (partialhash) partialhash(hashes, (const unsigned char*)data, length, types); else hashes.compute(reinterpret_cast<const UINT8 *>(data), length, types); }
static bool read_hash_config(const char *hash_path, const util::hash_collection &hashes, const char *sysname, std::string &result) { /* open a file */ emu_file file(hash_path, OPEN_FLAG_READ); if (file.open(sysname, ".hsi") != osd_file::error::NONE) { return false; } pugi::xml_document doc; pugi::xml_parse_result res = doc.load_file(file.fullpath()); if (res) { // Do search by CRC32 and SHA1 std::string query = "/hashfile/hash["; auto crc = hashes.internal_string().substr(1,8); auto sha1 = hashes.internal_string().substr(10, 40); query += "@crc32='" + crc + "' and @sha1='" + sha1 + "']/extrainfo"; pugi::xpath_node_set tools = doc.select_nodes(query.c_str()); for (pugi::xpath_node_set::const_iterator it = tools.begin(); it != tools.end(); ++it) { result = it->node().first_child().value(); return true; } // Try search by CRC32 only query = "/hashfile/hash["; query += "@crc32='" + crc + "']/extrainfo"; tools = doc.select_nodes(query.c_str()); for (pugi::xpath_node_set::const_iterator it = tools.begin(); it != tools.end(); ++it) { result = it->node().first_child().value(); return true; } } return false; }
void device_image_interface::run_hash(void (*partialhash)(util::hash_collection &, const unsigned char *, unsigned long, const char *), util::hash_collection &hashes, const char *types) { UINT32 size; dynamic_buffer buf; hashes.reset(); size = (UINT32) length(); buf.resize(size); memset(&buf[0], 0, size); // read the file fseek(0, SEEK_SET); fread(&buf[0], size); if (partialhash) partialhash(hashes, &buf[0], size, types); else hashes.compute(&buf[0], size, types); // cleanup fseek(0, SEEK_SET); }
void media_identifier::file_info::match( device_t const &device, romload::file const &rom, util::hash_collection const &hashes) { if (hashes == m_hashes) { m_matches.emplace_back( device.shortname(), device.name(), rom.get_name(), hashes.flag(util::hash_collection::FLAG_BAD_DUMP), device.owner()); } }
void rom_load_manager::verify_length_and_hash(const char *name, UINT32 explength, const util::hash_collection &hashes) { /* we've already complained if there is no file */ if (m_file == nullptr) return; /* verify length */ UINT32 actlength = m_file->size(); if (explength != actlength) { m_errorstring.append(string_format("%s WRONG LENGTH (expected: %08x found: %08x)\n", name, explength, actlength)); m_warnings++; } /* If there is no good dump known, write it */ util::hash_collection &acthashes = m_file->hashes(hashes.hash_types().c_str()); if (hashes.flag(util::hash_collection::FLAG_NO_DUMP)) { m_errorstring.append(string_format("%s NO GOOD DUMP KNOWN\n", name)); m_knownbad++; } /* verify checksums */ else if (hashes != acthashes) { /* otherwise, it's just bad */ m_errorstring.append(string_format("%s WRONG CHECKSUMS:\n", name)); dump_wrong_and_correct_checksums(hashes, acthashes); m_warnings++; } /* If it matches, but it is actually a bad dump, write it */ else if (hashes.flag(util::hash_collection::FLAG_BAD_DUMP)) { m_errorstring.append(string_format("%s ROM NEEDS REDUMP\n", name)); m_knownbad++; } }
void media_identifier::file_info::match( std::string const &list, software_info const &software, rom_entry const &rom, util::hash_collection const &hashes) { if (hashes == m_hashes) { m_matches.emplace_back( util::string_format("%s:%s", list, software.shortname()), std::string(software.longname()), ROM_GETNAME(&rom), hashes.flag(util::hash_collection::FLAG_BAD_DUMP), false); } }
static void dump_wrong_and_correct_checksums(const util::hash_collection &hashes, const util::hash_collection &acthashes) { osd_printf_error(" EXPECTED: %s\n", hashes.macro_string().c_str()); osd_printf_error(" FOUND: %s\n", acthashes.macro_string().c_str()); }
void media_identifier::match_hashes(std::vector<file_info> &info) { std::unordered_set<std::string> listnames; // iterate over drivers m_drivlist.reset(); while (m_drivlist.next()) { // iterate over regions and files within the region device_t &device = m_drivlist.config()->root_device(); for (romload::region const ®ion : romload::entries(device.rom_region()).get_regions()) { for (romload::file const &rom : region.get_files()) { util::hash_collection const romhashes(rom.get_hashdata()); if (!romhashes.flag(util::hash_collection::FLAG_NO_DUMP)) { for (file_info &file : info) file.match(device, rom, romhashes); } } } // next iterate over softlists for (software_list_device &swlistdev : software_list_device_iterator(device)) { if (listnames.insert(swlistdev.list_name()).second) { for (software_info const &swinfo : swlistdev.get_info()) { for (software_part const &part : swinfo.parts()) { for (rom_entry const *region = part.romdata().data(); region; region = rom_next_region(region)) { for (rom_entry const *rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { util::hash_collection romhashes(ROM_GETHASHDATA(rom)); if (!romhashes.flag(util::hash_collection::FLAG_NO_DUMP)) { for (file_info &file : info) file.match(swlistdev.list_name(), swinfo, *rom, romhashes); } } } } } } } } // iterator over devices machine_config config(GAME_NAME(___empty), m_drivlist.options()); for (device_type type : registered_device_types) { // iterate over regions and files within the region device_t *const device = config.device_add(&config.root_device(), "_tmp", type, 0); for (romload::region const ®ion : romload::entries(device->rom_region()).get_regions()) { for (romload::file const &rom : region.get_files()) { util::hash_collection const romhashes(rom.get_hashdata()); if (!romhashes.flag(util::hash_collection::FLAG_NO_DUMP)) { for (file_info &file : info) file.match(*device, rom, romhashes); } } } config.device_remove(&config.root_device(), "_tmp"); } }
void rom_load_manager::dump_wrong_and_correct_checksums(const util::hash_collection &hashes, const util::hash_collection &acthashes) { m_errorstring.append(string_format(" EXPECTED: %s\n", hashes.macro_string().c_str())); m_errorstring.append(string_format(" FOUND: %s\n", acthashes.macro_string().c_str())); }