rom_load_manager::rom_load_manager(running_machine &machine) : m_machine(machine) { /* figure out which BIOS we are using */ device_iterator deviter(machine.config().root_device()); for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) { if (device->rom_region()) { std::string specbios; if (device->owner() == nullptr) { specbios.assign(machine.options().bios()); } else { specbios = machine.options().sub_value(std::string(device->owner()->tag()).c_str()+1,"bios"); if (specbios.empty()) { specbios = device->default_bios_tag(); } } determine_bios_rom(device, specbios.c_str()); } } /* count the total number of ROMs */ count_roms(); /* reset the disk list */ m_chd_list.clear(); /* process the ROM entries we were passed */ process_region_list(); /* display the results and exit */ display_rom_load_results(FALSE); }
void software_list_device::display_matches(const machine_config &config, const char *interface, const char *name) { // check if there is at least one software list software_list_device_iterator deviter(config.root_device()); if (deviter.first() != nullptr) osd_printf_error("\n\"%s\" approximately matches the following\n" "supported software items (best match first):\n\n", name); // iterate through lists for (software_list_device &swlistdev : deviter) { // get the top 16 approximate matches for the selected device interface (i.e. only carts for cartslot, etc.) const software_info *matches[16] = { nullptr }; swlistdev.find_approx_matches(name, ARRAY_LENGTH(matches), matches, interface); // if we found some, print them if (matches[0] != nullptr) { // different output depending on original system or compatible if (swlistdev.list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM) osd_printf_error("* Software list \"%s\" (%s) matches: \n", swlistdev.list_name().c_str(), swlistdev.description()); else osd_printf_error("* Compatible software list \"%s\" (%s) matches: \n", swlistdev.list_name().c_str(), swlistdev.description()); // print them out for (auto &match : matches) { if (match != nullptr) osd_printf_error("%-18s%s\n", match->shortname().c_str(), match->longname().c_str()); } osd_printf_error("\n"); } } }
void info_xml_creator::output_device_roms() { device_iterator deviter(m_drivlist.config().root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) if (device->owner() != NULL && device->shortname()!= NULL && strlen(device->shortname())!=0) fprintf(m_output, "\t\t<device_ref name=\"%s\"/>\n", xml_normalize_string(device->shortname())); }
int cartslot_image_device::process_cartridge(bool load) { const rom_entry *romrgn, *roment; int result = 0; device_iterator deviter(device().mconfig().root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) for (romrgn = rom_first_region(*device); romrgn != NULL; romrgn = rom_next_region(romrgn)) { roment = romrgn + 1; while(!ROMENTRY_ISREGIONEND(roment)) { if (ROMENTRY_GETTYPE(roment) == ROMENTRYTYPE_CARTRIDGE) { astring regiontag; this->device().siblingtag(regiontag, roment->_hashdata); if (strcmp(regiontag.cstr(),this->device().tag())==0) { result |= load_cartridge(romrgn, roment, load); /* if loading failed in any cart region, stop loading */ if (result) return result; } } roment++; } } return IMAGE_INIT_PASS; }
static void process_region_list(romload_private *romdata) { astring regiontag; /* loop until we hit the end */ device_iterator deviter(romdata->machine().root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) for (const rom_entry *region = rom_first_region(*device); region != NULL; region = rom_next_region(region)) { UINT32 regionlength = ROMREGION_GETLENGTH(region); rom_region_name(regiontag, *device, region); LOG(("Processing region \"%s\" (length=%X)\n", regiontag.cstr(), regionlength)); /* the first entry must be a region */ assert(ROMENTRY_ISREGION(region)); if (ROMREGION_ISROMDATA(region)) { /* if this is a device region, override with the device width and endianness */ UINT8 width = ROMREGION_GETWIDTH(region) / 8; endianness_t endianness = ROMREGION_ISBIGENDIAN(region) ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; if (romdata->machine().device(regiontag) != NULL) normalize_flags_for_device(romdata->machine(), regiontag, width, endianness); /* 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 /* now process the entries in the region */ process_rom_entries(romdata, device->shortname(), region, region + 1, device, FALSE); } else if (ROMREGION_ISDISKDATA(region)) process_disk_entries(romdata, regiontag, region, region + 1, NULL); } /* now go back and post-process all the regions */ for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) for (const rom_entry *region = rom_first_region(*device); region != NULL; region = rom_next_region(region)) { rom_region_name(regiontag, *device, region); region_post_process(romdata, regiontag, ROMREGION_ISINVERTED(region)); } }
void info_xml_creator::output_devices() { m_drivlist.reset(); slot_map shortnames; while (m_drivlist.next()) { // first, run through devices with roms which belongs to the default configuration device_iterator deviter(m_drivlist.config().root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) { if (device->owner() != NULL && device->shortname()!= NULL && strlen(device->shortname())!=0) { if (shortnames.add(device->shortname(), 0, FALSE) != TMERR_DUPLICATE) output_one_device(*device, device->tag()); } } // then, run through slot devices slot_interface_iterator iter(m_drivlist.config().root_device()); for (const device_slot_interface *slot = iter.first(); slot != NULL; slot = iter.next()) { for (const device_slot_option *option = slot->first_option(); option != NULL; option = option->next()) { std::string temptag("_"); temptag.append(option->name()); device_t *dev = const_cast<machine_config &>(m_drivlist.config()).device_add(&m_drivlist.config().root_device(), temptag.c_str(), option->devtype(), 0); // notify this device and all its subdevices that they are now configured device_iterator subiter(*dev); for (device_t *device = subiter.first(); device != NULL; device = subiter.next()) if (!device->configured()) device->config_complete(); if (shortnames.add(dev->shortname(), 0, FALSE) != TMERR_DUPLICATE) output_one_device(*dev, temptag.c_str()); // also, check for subdevices with ROMs (a few devices are missed otherwise, e.g. MPU401) device_iterator deviter2(*dev); for (device_t *device = deviter2.first(); device != NULL; device = deviter2.next()) { if (device->owner() == dev && device->shortname()!= NULL && strlen(device->shortname())!=0) { if (shortnames.add(device->shortname(), 0, FALSE) != TMERR_DUPLICATE) output_one_device(*device, device->tag()); } } const_cast<machine_config &>(m_drivlist.config()).device_remove(&m_drivlist.config().root_device(), temptag.c_str()); } } } }
void driver_enumerator::release_current() { // skip if no current entry if (m_current < 0 || m_current >= s_driver_count) return; // skip if we haven't cached a config if (m_config[m_current] == NULL) return; // iterate over software lists in this entry and reset software_list_device_iterator deviter(m_config[m_current]->root_device()); for (software_list_device *swlistdev = deviter.first(); swlistdev != NULL; swlistdev = deviter.next()) swlistdev->release(); }
software_part *device_image_interface::find_software_item(const char *path, bool restrict_to_interface) const { // split full software name into software list name and short software name std::string swlist_name, swinfo_name, swpart_name; software_name_split(path, swlist_name, swinfo_name, swpart_name); // determine interface const char *interface = nullptr; if (restrict_to_interface) interface = image_interface(); // find the software list if explicitly specified software_list_device_iterator deviter(device().mconfig().root_device()); for (software_list_device *swlistdev = deviter.first(); swlistdev != nullptr; swlistdev = deviter.next()) { if (swlist_name.compare(swlistdev->list_name())==0 || !(swlist_name.length() > 0)) { software_info *info = swlistdev->find(swinfo_name.c_str()); if (info != nullptr) { software_part *part = info->find_part(swpart_name.c_str(), interface); if (part != nullptr) return part; } } if (swinfo_name == swlistdev->list_name()) { // ad hoc handling for the case path = swlist_name:swinfo_name (e.g. // gameboy:sml) which is not handled properly by software_name_split // since the function cannot distinguish between this and the case // path = swinfo_name:swpart_name software_info *info = swlistdev->find(swpart_name.c_str()); if (info != nullptr) { software_part *part = info->find_part(nullptr, interface); if (part != nullptr) return part; } } } // if explicitly specified and not found, just error here return nullptr; }
ui_menu_device_config::ui_menu_device_config(running_machine &machine, render_container *container, device_slot_interface *slot, device_slot_option *option) : ui_menu(machine, container) { astring tmp_tag; tmp_tag.cpy(slot->device().tag()).cat(":").cat(option->name()); m_option = option; m_owner = slot; m_mounted = false; device_iterator deviter(machine.config().root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) { if (strcmp(device->tag(), tmp_tag.cstr()) == 0) { m_mounted = true; break; } } }
void info_xml_creator::output_devices() { m_drivlist.reset(); slot_map shortnames; while (m_drivlist.next()) { // first, run through devices with roms which belongs to the default configuration device_iterator deviter(m_drivlist.config().root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) { if (device->owner() != NULL && device->rom_region() != NULL && device->shortname()!= NULL) { if (shortnames.add(device->shortname(), 0, FALSE) != TMERR_DUPLICATE) output_one_device(*device, device->tag()); } } // then, run through slot devices slot_interface_iterator iter(m_drivlist.config().root_device()); for (const device_slot_interface *slot = iter.first(); slot != NULL; slot = iter.next()) { const slot_interface* intf = slot->get_slot_interfaces(); for (int i = 0; intf && intf[i].name != NULL; i++) { astring temptag("_"); temptag.cat(intf[i].name); device_t *dev = const_cast<machine_config &>(m_drivlist.config()).device_add(&m_drivlist.config().root_device(), temptag.cstr(), intf[i].devtype, 0); // notify this device and all its subdevices that they are now configured device_iterator subiter(*dev); for (device_t *device = subiter.first(); device != NULL; device = subiter.next()) if (!device->configured()) device->config_complete(); if (shortnames.add(dev->shortname(), 0, FALSE) != TMERR_DUPLICATE) output_one_device(*dev, temptag.cstr()); const_cast<machine_config &>(m_drivlist.config()).device_remove(&m_drivlist.config().root_device(), temptag.cstr()); global_free(dev); } } } }
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 */ device_iterator deviter(machine().config().root_device()); for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) 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); } }
void rom_init(running_machine &machine) { romload_private *romdata; /* allocate private data */ machine.romload_data = romdata = auto_alloc_clear(machine, romload_private); /* make sure we get called back on the way out */ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(rom_exit), &machine)); /* reset the romdata struct */ romdata->m_machine = &machine; /* figure out which BIOS we are using */ device_iterator deviter(romdata->machine().config().root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) { if (device->rom_region()) { const char *specbios; astring temp; if (strcmp(device->tag(),":")==0) { specbios = romdata->machine().options().bios(); } else { specbios = romdata->machine().options().sub_value(temp,device->owner()->tag()+1,"bios"); if (strlen(specbios) == 0) { specbios = device->default_bios_tag().cstr(); } } determine_bios_rom(romdata, device, specbios); } } /* count the total number of ROMs */ count_roms(romdata); /* reset the disk list */ romdata->chd_list.reset(); /* process the ROM entries we were passed */ process_region_list(romdata); /* display the results and exit */ display_rom_load_results(romdata, FALSE); }
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); } }
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; }
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); }
software_part *device_image_interface::find_software_item(const char *path, bool restrict_to_interface) { // // Note: old code would explicitly load swlist_name if it was specified, rather than // searching the devices. // // Also if not found, old code would attempt to open <drivername>.xml and even // <swinfo_name>.xml. Hopefully removing this won't break anything. // // split full software name into software list name and short software name astring swlist_name, swinfo_name, swpart_name; software_name_split(path, swlist_name, swinfo_name, swpart_name); bool explicit_name = (swlist_name.len() > 0); // determine interface const char *interface = NULL; if (restrict_to_interface) interface = image_interface(); // find the software list if explicitly specified software_list_device_iterator deviter(device().mconfig().root_device()); for (software_list_device *swlistdev = deviter.first(); swlistdev != NULL; swlistdev = deviter.next()) if (!explicit_name || swlist_name == swlistdev->list_name()) { software_info *info = swlistdev->find(swinfo_name); if (info != NULL) { software_part *part = info->find_part(swpart_name, interface); if (part != NULL) return part; } } // if explicitly specified and not found, just error here return NULL; }
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; }
const char *info_xml_creator::get_merge_name(const hash_collection &romhashes) { // walk the parent chain const char *merge_name = NULL; 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 device_iterator deviter(m_drivlist.config(clone_of, m_lookup_options).root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) for (const rom_entry *pregion = rom_first_region(*device); 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 rom_load_manager::process_region_list() { std::string regiontag; /* loop until we hit the end */ device_iterator deviter(machine().root_device()); for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) for (const rom_entry *region = rom_first_region(*device); region != nullptr; region = rom_next_region(region)) { UINT32 regionlength = ROMREGION_GETLENGTH(region); regiontag = rom_region_name(*device, region); LOG(("Processing region \"%s\" (length=%X)\n", regiontag.c_str(), regionlength)); /* the first entry must be a region */ assert(ROMENTRY_ISREGION(region)); if (ROMREGION_ISROMDATA(region)) { /* if this is a device region, override with the device width and endianness */ UINT8 width = ROMREGION_GETWIDTH(region) / 8; endianness_t endianness = ROMREGION_ISBIGENDIAN(region) ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; if (machine().device(regiontag.c_str()) != nullptr) normalize_flags_for_device(machine(), regiontag.c_str(), width, endianness); /* remember the base and length */ m_region = machine().memory().region_alloc(regiontag.c_str(), regionlength, width, endianness); LOG(("Allocated %X bytes @ %p\n", m_region->bytes(), m_region->base())); /* clear the region if it's requested */ if (ROMREGION_ISERASE(region)) memset(m_region->base(), ROMREGION_GETERASEVAL(region), m_region->bytes()); /* or if it's sufficiently small (<= 4MB) */ else if (m_region->bytes() <= 0x400000) memset(m_region->base(), 0, m_region->bytes()); #ifdef MAME_DEBUG /* if we're debugging, fill region with random data to catch errors */ else fill_random(m_region->base(), m_region->bytes()); #endif /* now process the entries in the region */ process_rom_entries(device->shortname().c_str(), region, region + 1, device, FALSE); } else if (ROMREGION_ISDISKDATA(region)) process_disk_entries(regiontag.c_str(), region, region + 1, nullptr); } /* now go back and post-process all the regions */ for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) for (const rom_entry *region = rom_first_region(*device); region != nullptr; region = rom_next_region(region)) { regiontag = rom_region_name(*device, region); region_post_process(regiontag.c_str(), ROMREGION_ISINVERTED(region)); } /* and finally register all per-game parameters */ for (device_t *device = deviter.first(); device != nullptr; device = deviter.next()) for (const rom_entry *param = rom_first_parameter(*device); param != nullptr; param = rom_next_parameter(param)) { regiontag = rom_parameter_name(*device, param); machine().parameters().add(regiontag, rom_parameter_value(param)); } }
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; }
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); }
void device_memory_interface::interface_validity_check(validity_checker &valid) const { bool detected_overlap = DETECT_OVERLAPPING_MEMORY ? false : true; // loop over all address spaces for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; spacenum++) { const address_space_config *spaceconfig = space_config(spacenum); if (spaceconfig != NULL) { int datawidth = spaceconfig->m_databus_width; int alignunit = datawidth / 8; // construct the maps ::address_map *map = global_alloc(::address_map(const_cast<device_t &>(device()), spacenum)); // if this is an empty map, just skip it if (map->m_entrylist.first() == NULL) { global_free(map); continue; } // validate the global map parameters if (map->m_spacenum != spacenum) osd_printf_error("Space %d has address space %d handlers!\n", spacenum, map->m_spacenum); if (map->m_databits != datawidth) osd_printf_error("Wrong memory handlers provided for %s space! (width = %d, memory = %08x)\n", spaceconfig->m_name, datawidth, map->m_databits); // loop over entries and look for errors for (address_map_entry *entry = map->m_entrylist.first(); entry != NULL; entry = entry->next()) { UINT32 bytestart = spaceconfig->addr2byte(entry->m_addrstart); UINT32 byteend = spaceconfig->addr2byte_end(entry->m_addrend); // look for overlapping entries if (!detected_overlap) { address_map_entry *scan; for (scan = map->m_entrylist.first(); scan != entry; scan = scan->next()) if (entry->m_addrstart <= scan->m_addrend && entry->m_addrend >= scan->m_addrstart && ((entry->m_read.m_type != AMH_NONE && scan->m_read.m_type != AMH_NONE) || (entry->m_write.m_type != AMH_NONE && scan->m_write.m_type != AMH_NONE))) { osd_printf_warning("%s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_read.m_type, entry->m_write.m_type, scan->m_addrstart, scan->m_addrend, scan->m_read.m_type, scan->m_write.m_type); detected_overlap = true; break; } } // look for inverted start/end pairs if (byteend < bytestart) osd_printf_error("Wrong %s memory read handler start = %08x > end = %08x\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend); // look for misaligned entries if ((bytestart & (alignunit - 1)) != 0 || (byteend & (alignunit - 1)) != (alignunit - 1)) osd_printf_error("Wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, alignunit); // if this is a program space, auto-assign implicit ROM entries if (entry->m_read.m_type == AMH_ROM && entry->m_region == NULL) { entry->m_region = device().tag(); entry->m_rgnoffs = entry->m_addrstart; } // if this entry references a memory region, validate it if (entry->m_region != NULL && entry->m_share == 0) { // make sure we can resolve the full path to the region bool found = false; astring entry_region; entry->m_devbase.subtag(entry_region, entry->m_region); // look for the region device_iterator deviter(device().mconfig().root_device()); for (device_t *device = deviter.first(); device != NULL; device = deviter.next()) for (const rom_entry *romp = rom_first_region(*device); romp != NULL && !found; romp = rom_next_region(romp)) { astring fulltag; rom_region_name(fulltag, *device, romp); if (fulltag == entry_region) { // verify the address range is within the region's bounds offs_t length = ROMREGION_GETLENGTH(romp); if (entry->m_rgnoffs + (byteend - bytestart + 1) > length) osd_printf_error("%s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region, length); found = true; } } // error if not found if (!found) osd_printf_error("%s space memory map entry %X-%X references non-existant region '%s'\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region); } // make sure all devices exist // FIXME: This doesn't work! AMH_DEVICE_DELEGATE entries don't even set m_tag, the device tag is inside the proto-delegate if (entry->m_read.m_type == AMH_DEVICE_DELEGATE && entry->m_read.m_tag != NULL) { astring temp(entry->m_read.m_tag); if (device().siblingdevice(temp) == NULL) osd_printf_error("%s space memory map entry references nonexistant device '%s'\n", spaceconfig->m_name, entry->m_read.m_tag); } if (entry->m_write.m_type == AMH_DEVICE_DELEGATE && entry->m_write.m_tag != NULL) { astring temp(entry->m_write.m_tag); if (device().siblingdevice(temp) == NULL) osd_printf_error("%s space memory map entry references nonexistant device '%s'\n", spaceconfig->m_name, entry->m_write.m_tag); } // make sure ports exist // if ((entry->m_read.m_type == AMH_PORT && entry->m_read.m_tag != NULL && portlist.find(entry->m_read.m_tag) == NULL) || // (entry->m_write.m_type == AMH_PORT && entry->m_write.m_tag != NULL && portlist.find(entry->m_write.m_tag) == NULL)) // osd_printf_error("%s space memory map entry references nonexistant port tag '%s'\n", spaceconfig->m_name, entry->m_read.m_tag); // validate bank and share tags if (entry->m_read.m_type == AMH_BANK) valid.validate_tag(entry->m_read.m_tag); if (entry->m_write.m_type == AMH_BANK) valid.validate_tag(entry->m_write.m_tag); if (entry->m_share != NULL) valid.validate_tag(entry->m_share); } // release the address map global_free(map); } } }
static void InitDriversInfo(void) { int ndriver; int num_speakers = 0; int total = driver_list::total(); const game_driver *gamedrv = NULL; struct DriversInfo *gameinfo = NULL; const rom_entry *region, *rom; for (ndriver = 0; ndriver < total; ndriver++) { gamedrv = &driver_list::driver(ndriver); gameinfo = &drivers_info[ndriver]; machine_config config(*gamedrv, MameUIGlobal()); gameinfo->isClone = (GetParentRomSetIndex(gamedrv) != -1); gameinfo->isBroken = (gamedrv->flags & MACHINE_NOT_WORKING) ? true : false; gameinfo->isHarddisk = FALSE; gameinfo->isVertical = (gamedrv->flags & ORIENTATION_SWAP_XY) ? TRUE : FALSE; device_iterator deviter(config.root_device()); for (device_t *device = deviter.first(); device; device = deviter.next()) for (region = rom_first_region(*device); region; region = rom_next_region(region)) if (ROMREGION_ISDISKDATA(region)) gameinfo->isHarddisk = TRUE; gameinfo->hasOptionalBIOS = FALSE; if (gamedrv->rom) for (rom = gamedrv->rom; !ROMENTRY_ISEND(rom); rom++) if (ROMENTRY_ISSYSTEM_BIOS(rom)) gameinfo->hasOptionalBIOS = TRUE; num_speakers = numberOfSpeakers(&config); gameinfo->isStereo = (num_speakers > 1); gameinfo->screenCount = numberOfScreens(&config); gameinfo->isVector = isDriverVector(&config); gameinfo->usesRoms = FALSE; for (device_t *device = deviter.first(); device; device = deviter.next()) for (region = rom_first_region(*device); region; region = rom_next_region(region)) for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) gameinfo->usesRoms = TRUE; gameinfo->usesSamples = FALSE; samples_device_iterator iter(config.root_device()); if (iter.first()) gameinfo->usesSamples = TRUE; gameinfo->usesTrackball = FALSE; gameinfo->usesLightGun = FALSE; if (gamedrv->ipt) { ioport_port *port; ioport_list portlist; std::string errors; device_iterator iter(config.root_device()); for (device_t *cfg = iter.first(); cfg; cfg = iter.next()) if (cfg->input_ports()) portlist.append(*cfg, errors); for (port = portlist.first(); port; port = port->next()) { ioport_field *field; for (field = port->first_field(); field; field = field->next()) { UINT32 type; type = field->type(); if (type == IPT_END) break; if (type == IPT_DIAL || type == IPT_PADDLE || type == IPT_TRACKBALL_X || type == IPT_TRACKBALL_Y || type == IPT_AD_STICK_X || type == IPT_AD_STICK_Y) gameinfo->usesTrackball = TRUE; if (type == IPT_LIGHTGUN_X || type == IPT_LIGHTGUN_Y) gameinfo->usesLightGun = TRUE; if (type == IPT_MOUSE_X || type == IPT_MOUSE_Y) gameinfo->usesMouse = TRUE; } } } } SetDriversInfo(); }
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); }