//------------------------------------------------- // audit_one_disk - validate a single disk entry //------------------------------------------------- audit_record audit_one_disk(ListPointer <rom_entry> rom, string locationtag = null) //const rom_entry *rom { // allocate and append a new record audit_record record = m_record_list.emplace_back(new audit_record(rom, audit_record.media_type.MEDIA_DISK)).Value; //audit_record &record = *m_record_list.emplace(m_record_list.end(), *rom, media_type::DISK); // open the disk chd_file source = new chd_file(); chd_error err = (chd_error)romload_global.open_disk_image(m_enumerator.options(), m_enumerator.driver(), rom[0], source, locationtag); // if we succeeded, get the hashes if (err == chd_error.CHDERR_NONE) { util.hash_collection hashes = new util.hash_collection(); // if there's a SHA1 hash, add them to the output hash if (source.sha1() != null) { hashes.add_sha1(source.sha1()); } // update the actual values record.set_actual(hashes); } // compute the final status compute_status(record, rom[0], err == chd_error.CHDERR_NONE); return(record); }
public parent_rom(device_type t, Pointer <rom_entry> r) { type = t; name = r.op.name(); hashes = new util.hash_collection(r.op.hashdata()); length = rom_file_size(r); }
//------------------------------------------------- // audit_device - audit the device //------------------------------------------------- public summary audit_device(device_t device, string validation = AUDIT_VALIDATE_FULL) { // start fresh m_record_list.clear(); // 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 (ListPointer <rom_entry> region = romload_global.rom_first_region(device); region != null; region = romload_global.rom_next_region(region)) { for (ListPointer <rom_entry> rom = romload_global.rom_first_file(region); rom != null; rom = romload_global.rom_next_file(rom)) { util.hash_collection hashes = new util.hash_collection(romload_global.ROM_GETHASHDATA(rom[0])); // count the number of files with hashes if (!hashes.flag(util.hash_collection.FLAG_NO_DUMP) && !romload_global.ROM_ISOPTIONAL(rom[0])) { required++; } // audit a file audit_record record = null; if (romload_global.ROMREGION_ISROMDATA(region[0])) { record = audit_one_rom(rom); } // audit a disk else if (romload_global.ROMREGION_ISDISKDATA(region[0])) { record = audit_one_disk(rom); } // count the number of files that are found. if (record != null && (record.status() == audit_record.audit_status.STATUS_GOOD || record.status() == audit_record.audit_status.STATUS_FOUND_INVALID)) { found++; } } } if (found == 0 && required > 0) { m_record_list.clear(); return(summary.NOTFOUND); } // return a summary string unused = ""; return(summarize(device.shortname(), ref unused)); }
public audit_record(string name, media_type type) { m_next = null; m_type = type; m_status = audit_status.UNVERIFIED; m_substatus = audit_substatus.UNVERIFIED; m_name = name; m_explength = 0; m_length = 0; m_exphashes = new util.hash_collection(); m_hashes = new util.hash_collection(); m_shared_device = null; }
device_type m_shared_device; /* device that shares the rom */ //std::add_pointer_t<device_type> m_shared_device; // device that shares the ROM // construction/destruction //------------------------------------------------- // audit_record - constructor //------------------------------------------------- public audit_record(Pointer <rom_entry> media, media_type type) { m_next = null; m_type = type; m_status = audit_status.UNVERIFIED; m_substatus = audit_substatus.UNVERIFIED; m_name = media.op.name(); m_explength = rom_file_size(media); m_length = 0; m_exphashes = new util.hash_collection(media.op.hashdata()); m_hashes = new util.hash_collection(); m_shared_device = null; }
//------------------------------------------------- // find_shared_device - return the source that // shares a media entry with the same hashes //------------------------------------------------- device_t find_shared_device(device_t device, string name, util.hash_collection romhashes, UInt64 romlength) { bool dumped = !romhashes.flag(util.hash_collection.FLAG_NO_DUMP); // special case for non-root devices device_t highest_device = null; if (device.owner() != null) { for (ListPointer <rom_entry> region = romload_global.rom_first_region(device); region != null; region = romload_global.rom_next_region(region)) { for (ListPointer <rom_entry> rom = romload_global.rom_first_file(region); rom != null; rom = romload_global.rom_next_file(rom)) { if (romload_global.ROM_GETLENGTH(rom[0]) == romlength) { util.hash_collection hashes = new util.hash_collection(romload_global.ROM_GETHASHDATA(rom[0])); if ((dumped && hashes == romhashes) || (!dumped && romload_global.ROM_GETNAME(rom[0]) == name)) { highest_device = device; } } } } } else { // iterate up the parent chain for (int drvindex = driver_enumerator.find(m_enumerator.driver().parent); drvindex != -1; drvindex = driver_enumerator.find(driver_enumerator.driver(drvindex).parent)) { foreach (device_t scandevice in new device_iterator(m_enumerator.config(drvindex).root_device())) { for (ListPointer <rom_entry> region = romload_global.rom_first_region(scandevice); region != null; region = romload_global.rom_next_region(region)) { for (ListPointer <rom_entry> rom = romload_global.rom_first_file(region); rom != null; rom = romload_global.rom_next_file(rom)) { if (romload_global.ROM_GETLENGTH(rom[0]) == romlength) { util.hash_collection hashes = new util.hash_collection(romload_global.ROM_GETHASHDATA(rom[0])); if ((dumped && hashes == romhashes) || (!dumped && romload_global.ROM_GETNAME(rom[0]) == name)) { highest_device = scandevice; } } } } } } } return(highest_device); }
public device_type find_shared_device(device_t current, string name, util.hash_collection hashes, uint64_t length) //std::add_pointer_t<device_type> find_shared_device(device_t ¤t, char const *name, util::hash_collection const &hashes, uint64_t length) const { // if we're examining a child device, it will always have a perfect match if (current.owner() != null) { return(current.type()); } // scan backwards through parents for a matching definition bool dumped = !hashes.flag(util.hash_collection.FLAG_NO_DUMP); device_type best = null; foreach (var it in this.Reverse()) //for (const_reverse_iterator it = crbegin(); crend() != it; ++it) { if (it.length == length) { if (dumped) { if (it.hashes == hashes) { return(it.type); } } else if (it.name == name) { if (it.hashes.flag(util.hash_collection.FLAG_NO_DUMP)) { return(it.type); } else if (best == null) { best = it.type; } } } } return(best); }
// getters //const simple_list<audit_record> &records() const { return m_record_list; } // audit operations //------------------------------------------------- // audit_media - audit the media described by the // currently-enumerated driver //------------------------------------------------- public summary audit_media(string validation = AUDIT_VALIDATE_FULL) { // start fresh m_record_list.clear(); // store validation for later m_validation = validation; // temporary hack until romload is update: get the driver path and support it for // all searches string 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 foreach (device_t device in new device_iterator(m_enumerator.config().root_device())) { // determine the search path for this source and iterate through the regions m_searchpath = device.searchpath(); // now iterate over regions and ROMs within for (ListPointer <rom_entry> region = romload_global.rom_first_region(device); region != null; region = romload_global.rom_next_region(region)) { // temporary hack: add the driver path & region name string combinedpath = device.searchpath() + ";" + driverpath; if (!string.IsNullOrEmpty(device.shortname())) { combinedpath += ";" + device.shortname(); } m_searchpath = combinedpath; for (ListPointer <rom_entry> rom = romload_global.rom_first_file(region); rom != null; rom = romload_global.rom_next_file(rom)) { string name = romload_global.ROM_GETNAME(rom[0]); util.hash_collection hashes = new util.hash_collection(romload_global.ROM_GETHASHDATA(rom[0])); device_t shared_device = find_shared_device(device, name, hashes, romload_global.ROM_GETLENGTH(rom[0])); // count the number of files with hashes if (!hashes.flag(util.hash_collection.FLAG_NO_DUMP) && !romload_global.ROM_ISOPTIONAL(rom[0])) { required++; if (shared_device != null) { shared_required++; } } // audit a file audit_record record = null; if (romload_global.ROMREGION_ISROMDATA(region[0])) { record = audit_one_rom(rom); } // audit a disk else if (romload_global.ROMREGION_ISDISKDATA(region[0])) { record = audit_one_disk(rom); } if (record != null) { // count the number of files that are found. if (record.status() == audit_record.audit_status.STATUS_GOOD || (record.status() == audit_record.audit_status.STATUS_FOUND_INVALID && find_shared_device(device, name, record.actual_hashes(), record.actual_length()) == null)) { found++; if (shared_device != null) { 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.clear(); return(summary.NOTFOUND); } // return a summary string unused = ""; return(summarize(m_enumerator.driver().name, ref unused)); }
public void set_actual(util.hash_collection hashes, UInt64 length = 0) { m_hashes = hashes; m_length = length; }
public std.pair <device_type, bool> actual_matches_shared(device_t current, media_auditor.audit_record record) //std::pair<std::add_pointer_t<device_type>, bool> actual_matches_shared(device_t ¤t, media_auditor::audit_record const &record) { // no result if no matching file was found if ((record.status() != media_auditor.audit_status.GOOD) && (record.status() != media_auditor.audit_status.FOUND_INVALID)) { return(std.make_pair((device_type)null, false)); } // if we're examining a child device, scan it first bool matches_device_undumped = false; if (current.owner() != null) { for (Pointer <rom_entry> region = rom_first_region(current); region != null; region = rom_next_region(region)) { for (Pointer <rom_entry> rom = rom_first_file(region); rom != null; rom = rom_next_file(rom)) { if (rom_file_size(rom) == record.actual_length()) { util.hash_collection hashes = new util.hash_collection(rom.op.hashdata()); if (hashes == record.actual_hashes()) { return(std.make_pair(current.type(), empty())); } else if (hashes.flag(util.hash_collection.FLAG_NO_DUMP) && (rom.op.name() == record.name())) { matches_device_undumped = true; } } } } } // look for a matching parent ROM device_type closest_bad = null; foreach (var it in this.Reverse()) //for (const_reverse_iterator it = crbegin(); crend() != it; ++it) { if (it.length == record.actual_length()) { if (it.hashes == record.actual_hashes()) { return(std.make_pair(it.type, it.type == this[0].type)); } else if (it.hashes.flag(util.hash_collection.FLAG_NO_DUMP) && (it.name == record.name())) { closest_bad = it.type; } } } // fall back to the nearest bad dump if (closest_bad != null) { return(std.make_pair(closest_bad, this[0].type == closest_bad)); } else if (matches_device_undumped) { return(std.make_pair(current.type(), empty())); } else { return(std.make_pair((device_type)null, false)); } }
// audit operations //------------------------------------------------- // audit_media - audit the media described by the // currently-enumerated driver //------------------------------------------------- public summary audit_media(string validation = AUDIT_VALIDATE_FULL) { // start fresh m_record_list.clear(); // store validation for later m_validation = validation; // first walk the parent chain for required ROMs parent_rom_vector parentroms = new parent_rom_vector(); for (var drvindex = driver_list.find(m_enumerator.driver().parent); 0 <= drvindex; drvindex = driver_list.find(driver_list.driver((size_t)drvindex).parent)) //for (auto drvindex = m_enumerator.find(m_enumerator.driver().parent); 0 <= drvindex; drvindex = m_enumerator.find(m_enumerator.driver(drvindex).parent)) { game_driver parent = driver_list.driver((size_t)drvindex); LOG(null, "Checking parent {0} for ROM files\n", parent.type.shortname()); std.vector <rom_entry> roms = rom_build_entries(parent.rom); for (Pointer <rom_entry> region = rom_first_region(new Pointer <rom_entry>(roms)); region != null; region = rom_next_region(region)) //for (rom_entry const *region = rom_first_region(&roms.front()); region; region = rom_next_region(region)) { for (Pointer <rom_entry> rom = rom_first_file(region); rom != null; rom = rom_next_file(rom)) //for (rom_entry const *rom = rom_first_file(region); rom; rom = rom_next_file(rom)) { LOG(null, "Adding parent ROM {0}\n", rom.op.name()); parentroms.emplace_back(new parent_rom(parent.type, rom)); } } } parentroms.remove_redundant_parents(); // count ROMs required/found size_t found = 0; size_t required = 0; size_t shared_found = 0; size_t shared_required = 0; size_t parent_found = 0; // iterate over devices and regions std.vector <string> searchpath = new std.vector <string>(); foreach (device_t device in new device_enumerator(m_enumerator.config().root_device())) { searchpath.clear(); // now iterate over regions and ROMs within for (Pointer <rom_entry> region = rom_first_region(device); region != null; region = rom_next_region(region)) { for (Pointer <rom_entry> rom = rom_first_file(region); rom != null; rom = rom_next_file(rom)) { if (searchpath.empty()) { LOG(null, "Audit media for device {0}({1})\n", device.shortname(), device.tag()); searchpath = device.searchpath(); } // look for a matching parent or device ROM string name = rom.op.name(); util.hash_collection hashes = new util.hash_collection(rom.op.hashdata()); bool dumped = !hashes.flag(util.hash_collection.FLAG_NO_DUMP); device_type shared_device = parentroms.find_shared_device(device, name, hashes, rom_file_size(rom)); if (shared_device != null) { LOG(null, "File '{0}' {1}{2}dumped shared with {3}\n", name, ROM_ISOPTIONAL(rom.op) ? "optional " : "", dumped ? "" : "un", shared_device.shortname()); } else { LOG(null, "File '{0}' {1}{2}dumped\n", name, ROM_ISOPTIONAL(rom.op) ? "optional " : "", dumped ? "" : "un"); } // count the number of files with hashes if (dumped && !ROM_ISOPTIONAL(rom.op)) { required++; if (shared_device != null) { shared_required++; } } // audit a file audit_record record = null; if (ROMREGION_ISROMDATA(region.op)) { record = audit_one_rom(searchpath, rom); } // audit a disk else if (ROMREGION_ISDISKDATA(region.op)) { record = audit_one_disk(rom, device); } if (record != null) { // see if the actual content found belongs to a parent var matchesshared = parentroms.actual_matches_shared(device, record); if (matchesshared.first != null) { LOG(null, "Actual ROM file shared with {0}parent {1}\n", matchesshared.second ? "immediate " : "", matchesshared.first.shortname()); } // count the number of files that are found. if ((record.status() == audit_status.GOOD) || ((record.status() == audit_status.FOUND_INVALID) && (matchesshared.first == null))) { found++; if (shared_device != null) { shared_found++; } if (matchesshared.second) { parent_found++; } } record.set_shared_device(shared_device); } } } } if (!searchpath.empty()) { LOG(null, "Total required={0} (shared={1}) found={2} (shared={3} parent={4})\n", required, shared_required, found, shared_found, parent_found); } // 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) || parent_found == 0)) { m_record_list.clear(); return(summary.NOTFOUND); } // return a summary return(summarize(m_enumerator.driver().name)); }