std::string video_manager::speed_text() { std::string str; // if we're paused, just display Paused bool paused = machine().paused(); if (paused) str.append("paused"); // if we're fast forwarding, just display Fast-forward else if (m_fastforward) str.append("fast "); // if we're auto frameskipping, display that plus the level else if (effective_autoframeskip()) strcatprintf(str, "auto%2d/%d", effective_frameskip(), MAX_FRAMESKIP); // otherwise, just display the frameskip plus the level else strcatprintf(str, "skip %d/%d", effective_frameskip(), MAX_FRAMESKIP); // append the speed for all cases except paused if (!paused) strcatprintf(str, "%4d%%", (int)(100 * m_speed_percent + 0.5)); // display the number of partial updates as well int partials = 0; screen_device_iterator iter(machine().root_device()); for (screen_device *screen = iter.first(); screen != nullptr; screen = iter.next()) partials += screen->partial_updates(); if (partials > 1) strcatprintf(str, "\n%d partial updates", partials); return str; }
void info_xml_creator::output_switches(const ioport_list &portlist, const char *root_tag, int type, const char *outertag, const char *innertag) { // iterate looking for DIP switches for (ioport_port *port = portlist.first(); port != NULL; port = port->next()) for (ioport_field *field = port->first_field(); field != NULL; field = field->next()) if (field->type() == type) { std::string output; std::string newtag(port->tag()), oldtag(":"); newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length()); // output the switch name information std::string normalized_field_name(xml_normalize_string(field->name())); std::string normalized_newtag(xml_normalize_string(newtag.c_str())); strcatprintf(output,"\t\t<%s name=\"%s\" tag=\"%s\" mask=\"%u\">\n", outertag, normalized_field_name.c_str(), normalized_newtag.c_str(), field->mask()); // loop over settings for (ioport_setting *setting = field->first_setting(); setting != NULL; setting = setting->next()) { strcatprintf(output,"\t\t\t<%s name=\"%s\" value=\"%u\"%s/>\n", innertag, xml_normalize_string(setting->name()), setting->value(), setting->value() == field->defvalue() ? " default=\"yes\"" : ""); } // terminate the switch entry strcatprintf(output,"\t\t</%s>\n", outertag); fprintf(m_output, "%s", output.c_str()); } }
void ui_menu_audit::save_available_machines() { // attempt to open the output file emu_file file(machine().options().mewui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); if (file.open(emulator_info::get_configname(), "_avail.ini") == FILERR_NONE) { // generate header std::string buffer = std::string("#\n").append(MEWUI_VERSION_TAG).append(mewui_version).append("\n#\n\n"); strcatprintf(buffer, "%d\n", (int)m_availablesorted.size()); strcatprintf(buffer, "%d\n", (int)m_unavailablesorted.size()); // generate available list for (size_t x = 0; x < m_availablesorted.size(); ++x) { int find = driver_list::find(m_availablesorted[x]->name); strcatprintf(buffer, "%d\n", find); } // generate unavailable list for (size_t x = 0; x < m_unavailablesorted.size(); ++x) { int find = driver_list::find(m_unavailablesorted[x]->name); strcatprintf(buffer, "%d\n", find); } file.puts(buffer.c_str()); file.close(); } }
bool core_options::parse_ini_file(core_file &inifile, int priority, int ignore_priority, std::string &error_string) { // loop over lines in the file char buffer[4096]; while (core_fgets(buffer, ARRAY_LENGTH(buffer), &inifile) != nullptr) { // find the extent of the name char *optionname; for (optionname = buffer; *optionname != 0; optionname++) if (!isspace((UINT8)*optionname)) break; // skip comments if (*optionname == 0 || *optionname == '#') continue; // scan forward to find the first space char *temp; for (temp = optionname; *temp != 0; temp++) if (isspace((UINT8)*temp)) break; // if we hit the end early, print a warning and continue if (*temp == 0) { strcatprintf(error_string,"Warning: invalid line in INI: %s", buffer); continue; } // nullptr-terminate *temp++ = 0; char *optiondata = temp; // scan the data, stopping when we hit a comment bool inquotes = false; for (temp = optiondata; *temp != 0; temp++) { if (*temp == '"') inquotes = !inquotes; if (*temp == '#' && !inquotes) break; } *temp = 0; // find our entry auto curentry = m_entrymap.find(optionname); if (curentry == m_entrymap.end()) { if (priority >= ignore_priority) strcatprintf(error_string, "Warning: unknown option in INI: %s\n", optionname); continue; } // set the new data validate_and_set_data(*curentry->second, optiondata, priority, error_string); } return true; }
bool core_options::parse_command_line(int argc, char **argv, int priority, std::string &error_string) { // reset the errors and the command error_string.clear(); m_command.clear(); // iterate through arguments int unadorned_index = 0; bool retval = true; for (int arg = 1; arg < argc; arg++) { // determine the entry name to search for const char *curarg = argv[arg]; bool is_unadorned = (curarg[0] != '-'); const char *optionname = is_unadorned ? core_options::unadorned(unadorned_index++) : &curarg[1]; // find our entry; if not found, indicate invalid option auto curentry = m_entrymap.find(optionname); if (curentry == m_entrymap.end()) { strcatprintf(error_string, "Error: unknown option: %s\n", curarg); retval = false; if (!is_unadorned) arg++; continue; } // process commands first if (curentry->second->type() == OPTION_COMMAND) { // can only have one command if (!m_command.empty()) { strcatprintf(error_string,"Error: multiple commands specified -%s and %s\n", m_command.c_str(), curarg); return false; } m_command = curentry->second->name(); continue; } // get the data for this argument, special casing booleans const char *newdata; if (curentry->second->type() == OPTION_BOOLEAN) newdata = (strncmp(&curarg[1], "no", 2) == 0) ? "0" : "1"; else if (is_unadorned) newdata = curarg; else if (arg + 1 < argc) newdata = argv[++arg]; else { strcatprintf(error_string, "Error: option %s expected a parameter\n", curarg); return false; } // set the new data validate_and_set_data(*curentry->second, newdata, priority, error_string); } return retval; }
const char *core_options::output_ini(std::string &buffer, const core_options *diff) { // INI files are complete, so always start with a blank buffer buffer.clear(); int num_valid_headers = 0; int unadorned_index = 0; const char *last_header = nullptr; // loop over all items for (entry *curentry = m_entrylist.first(); curentry != nullptr; curentry = curentry->next()) { const char *name = curentry->name(); const char *value = curentry->value(); bool is_unadorned = false; // check if it's unadorned if (name && strlen(name) && !strcmp(name, core_options::unadorned(unadorned_index))) { unadorned_index++; is_unadorned = true; } // header: record description if (curentry->is_header()) last_header = curentry->description(); // otherwise, output entries for all non-command items else if (!curentry->is_command()) { if ( !curentry->is_internal() ) { // look up counterpart in diff, if diff is specified if (diff == nullptr || strcmp(value, diff->value(name)) != 0) { // output header, if we have one if (last_header != nullptr) { if (num_valid_headers++) strcatprintf(buffer,"\n"); strcatprintf(buffer, "#\n# %s\n#\n", last_header); last_header = nullptr; } // and finally output the data, skip if unadorned if (!is_unadorned) { if (strchr(value, ' ') != nullptr) strcatprintf(buffer,"%-25s \"%s\"\n", name, value); else strcatprintf(buffer,"%-25s %s\n", name, value); } } } } } return buffer.c_str(); }
void debug_view_breakpoints::pad_astring_to_length(std::string& str, int len) { int diff = len - str.length(); if (diff > 0) { std::string buffer; for (int i = 0; i < diff; i++) strcatprintf(buffer, " "); strcatprintf(str, "%s", buffer.c_str()); } }
void emu_options::add_device_options(bool isfirstpass) { // look up the system configured by name; if no match, do nothing const game_driver *cursystem = system(); if (cursystem == NULL) return; machine_config config(*cursystem, *this); // iterate through all image devices bool first = true; image_interface_iterator iter(config.root_device()); for (const device_image_interface *image = iter.first(); image != NULL; image = iter.next()) { // first device? add the header as to be pretty if (first && isfirstpass) add_entry(NULL, "IMAGE DEVICES", OPTION_HEADER | OPTION_FLAG_DEVICE); first = false; // retrieve info about the device instance std::string option_name; strprintf(option_name, "%s;%s", image->instance_name(), image->brief_instance_name()); if (strcmp(image->device_typename(image->image_type()), image->instance_name()) == 0) strcatprintf(option_name, ";%s1;%s1", image->instance_name(), image->brief_instance_name()); // add the option if (!exists(image->instance_name())) add_entry(option_name.c_str(), NULL, OPTION_STRING | OPTION_FLAG_DEVICE, NULL, true); } }
const char *core_options::output_help(std::string &buffer) { // start empty buffer.clear(); // loop over all items for (entry *curentry = m_entrylist.first(); curentry != nullptr; curentry = curentry->next()) { // header: just print if (curentry->is_header()) strcatprintf(buffer,"\n#\n# %s\n#\n", curentry->description()); // otherwise, output entries for all non-deprecated items else if (curentry->description() != nullptr) strcatprintf(buffer,"-%-20s%s\n", curentry->name(), curentry->description()); } return buffer.c_str(); }
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++; } }
bool core_options::set_value(const char *name, const char *value, int priority, std::string &error_string) { // find the entry first auto curentry = m_entrymap.find(name); if (curentry == m_entrymap.end()) { strcatprintf(error_string, "Attempted to set unknown option %s\n", name); return false; } // validate and set the item normally return validate_and_set_data(*curentry->second, value, priority, error_string); }
void ui_menu_bookkeeping::populate() { int tickets = machine().bookkeeping().get_dispensed_tickets(); std::string tempstring; int ctrnum; /* show total time first */ if (prevtime.seconds() >= 60 * 60) strcatprintf(tempstring, "Uptime: %d:%02d:%02d\n\n", prevtime.seconds() / (60 * 60), (prevtime.seconds() / 60) % 60, prevtime.seconds() % 60); else strcatprintf(tempstring,"Uptime: %d:%02d\n\n", (prevtime.seconds() / 60) % 60, prevtime.seconds() % 60); /* show tickets at the top */ if (tickets > 0) strcatprintf(tempstring,"Tickets dispensed: %d\n\n", tickets); /* loop over coin counters */ for (ctrnum = 0; ctrnum < COIN_COUNTERS; ctrnum++) { int count = machine().bookkeeping().coin_counter_get_count(ctrnum); /* display the coin counter number */ strcatprintf(tempstring,"Coin %c: ", ctrnum + 'A'); /* display how many coins */ if (count == 0) tempstring.append("NA"); else strcatprintf(tempstring, "%d", count); /* display whether or not we are locked out */ if (machine().bookkeeping().coin_lockout_get_state(ctrnum)) tempstring.append(" (locked)"); tempstring.append("\n"); } /* append the single item */ item_append(tempstring.c_str(), nullptr, MENU_FLAG_MULTILINE, nullptr); }
void favorite_manager::save_favorite_games() { // attempt to open the output file emu_file file(machine().ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); if (file.open(favorite_filename) == FILERR_NONE) { if (m_list.empty()) { file.remove_on_close(); file.close(); return; } // generate the favorite INI std::string text("[ROOT_FOLDER]\n[Favorite]\n\n"); for (auto & elem : m_list) { text += elem.shortname + "\n"; text += elem.longname + "\n"; text += elem.parentname + "\n"; text += elem.year + "\n"; text += elem.publisher + "\n"; strcatprintf(text, "%d\n", elem.supported); text += elem.part + "\n"; strcatprintf(text, "%s\n", elem.driver->name); text += elem.listname + "\n"; text += elem.interface + "\n"; text += elem.instance + "\n"; strcatprintf(text, "%d\n", elem.startempty); text += elem.parentlongname + "\n"; text += elem.usage + "\n"; text += elem.devicetype + "\n"; strcatprintf(text, "%d\n", elem.available); } file.puts(text.c_str()); file.close(); } }
void rom_load_manager::verify_length_and_hash(const char *name, UINT32 explength, const 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) { strcatprintf(m_errorstring, "%s WRONG LENGTH (expected: %08x found: %08x)\n", name, explength, actlength); m_warnings++; } /* If there is no good dump known, write it */ hash_collection &acthashes = m_file->hashes(hashes.hash_types().c_str()); if (hashes.flag(hash_collection::FLAG_NO_DUMP)) { strcatprintf(m_errorstring, "%s NO GOOD DUMP KNOWN\n", name); m_knownbad++; } /* verify checksums */ else if (hashes != acthashes) { /* otherwise, it's just bad */ strcatprintf(m_errorstring, "%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(hash_collection::FLAG_BAD_DUMP)) { strcatprintf(m_errorstring, "%s ROM NEEDS REDUMP\n",name); m_knownbad++; } }
void rom_load_manager::determine_bios_rom(device_t *device, const char *specbios) { const char *defaultname = nullptr; const rom_entry *rom; int default_no = 1; int bios_count = 0; device->set_system_bios(0); /* first determine the default BIOS name */ for (rom = device->rom_region(); !ROMENTRY_ISEND(rom); rom++) if (ROMENTRY_ISDEFAULT_BIOS(rom)) defaultname = ROM_GETNAME(rom); /* look for a BIOS with a matching name */ for (rom = device->rom_region(); !ROMENTRY_ISEND(rom); rom++) if (ROMENTRY_ISSYSTEM_BIOS(rom)) { const char *biosname = ROM_GETNAME(rom); int bios_flags = ROM_GETBIOSFLAGS(rom); char bios_number[20]; /* Allow '-bios n' to still be used */ sprintf(bios_number, "%d", bios_flags - 1); if (core_stricmp(bios_number, specbios) == 0 || core_stricmp(biosname, specbios) == 0) device->set_system_bios(bios_flags); if (defaultname != nullptr && core_stricmp(biosname, defaultname) == 0) default_no = bios_flags; bios_count++; } /* if none found, use the default */ if (device->system_bios() == 0 && bios_count > 0) { /* if we got neither an empty string nor 'default' then warn the user */ if (specbios[0] != 0 && strcmp(specbios, "default") != 0) { strcatprintf(m_errorstring, "%s: invalid bios\n", specbios); m_errors++; } /* set to default */ device->set_system_bios(default_no); } device->set_default_bios(default_no); LOG(("For \"%s\" using System BIOS: %d\n", device->tag().c_str(), device->system_bios())); }
bool emu_options::parse_one_ini(const char *basename, int priority, std::string *error_string) { // don't parse if it has been disabled if (!read_config()) return false; // open the file; if we fail, that's ok emu_file file(ini_path(), OPEN_FLAG_READ); file_error filerr = file.open(basename, ".ini"); if (filerr != FILERR_NONE) return false; // parse the file osd_printf_verbose("Parsing %s.ini\n", basename); std::string error; bool result = parse_ini_file(file, priority, OPTION_PRIORITY_DRIVER_INI, error); // append errors if requested if (!error.empty() && error_string != NULL) strcatprintf(*error_string, "While parsing %s:\n%s\n", file.fullpath(), error.c_str()); return result; }
void ui_menu_bios_selection::handle() { /* process the menu */ const ui_menu_event *menu_event = process(0); if (menu_event != nullptr && menu_event->itemref != nullptr) { if ((FPTR)menu_event->itemref == 1 && menu_event->iptkey == IPT_UI_SELECT) machine().schedule_hard_reset(); else if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) { device_t *dev = (device_t *)menu_event->itemref; int cnt = 0; for (const rom_entry *rom = dev->rom_region(); !ROMENTRY_ISEND(rom); rom++) { if (ROMENTRY_ISSYSTEM_BIOS(rom)) cnt ++; } int val = dev->system_bios() + ((menu_event->iptkey == IPT_UI_LEFT) ? -1 : +1); if (val<1) val=cnt; if (val>cnt) val=1; dev->set_system_bios(val); if (strcmp(dev->tag(),":")==0) { std::string error; machine().options().set_value("bios", val-1, OPTION_PRIORITY_CMDLINE, error); assert(error.empty()); } else { std::string error; std::string value = machine().options().main_value(dev->owner()->tag()+1); strcatprintf(value,",bios=%d",val-1); machine().options().set_value(dev->owner()->tag()+1, value.c_str(), OPTION_PRIORITY_CMDLINE, error); assert(error.empty()); } reset(UI_MENU_RESET_REMEMBER_REF); } } }
void rom_load_manager::dump_wrong_and_correct_checksums(const hash_collection &hashes, const hash_collection &acthashes) { strcatprintf(m_errorstring, " EXPECTED: %s\n", hashes.macro_string().c_str()); strcatprintf(m_errorstring, " FOUND: %s\n", acthashes.macro_string().c_str()); }
void rom_load_manager::load_software_part_region(device_t &device, software_list_device &swlist, const char *swname, const rom_entry *start_region) { std::string locationtag(swlist.list_name()), breakstr("%"); const rom_entry *region; std::string regiontag; m_errorstring.clear(); m_softwarningstring.clear(); m_romstotal = 0; m_romstotalsize = 0; m_romsloadedsize = 0; software_info *swinfo = swlist.find(swname); if (swinfo != nullptr) { UINT32 supported = swinfo->supported(); if (supported == SOFTWARE_SUPPORTED_PARTIAL) { strcatprintf(m_errorstring, "WARNING: support for software %s (in list %s) is only partial\n", swname, swlist.list_name()); strcatprintf(m_softwarningstring, "Support for software %s (in list %s) is only partial\n", swname, swlist.list_name()); } if (supported == SOFTWARE_SUPPORTED_NO) { strcatprintf(m_errorstring, "WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist.list_name()); strcatprintf(m_softwarningstring, "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 " // open_rom_file contains the code to split the elements and to create paths to load from locationtag.append(breakstr); 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); } /* loop until we hit the end */ for (region = start_region; region != nullptr; region = rom_next_region(region)) { UINT32 regionlength = ROMREGION_GETLENGTH(region); regiontag = device.subtag(ROMREGION_GETTAG(region)); LOG(("Processing region \"%s\" (length=%X)\n", regiontag.c_str(), regionlength)); /* the first entry must be a region */ assert(ROMENTRY_ISREGION(region)); /* if this is a device region, override with the device width and endianness */ endianness_t endianness = ROMREGION_ISBIGENDIAN(region) ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; UINT8 width = ROMREGION_GETWIDTH(region) / 8; memory_region *memregion = machine().root_device().memregion(regiontag.c_str()); if (memregion != nullptr) { if (machine().device(regiontag.c_str()) != nullptr) normalize_flags_for_device(machine(), regiontag.c_str(), width, endianness); /* clear old region (todo: should be moved to an image unload function) */ machine().memory().region_free(memregion->name()); } /* 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 /* update total number of roms */ for (const rom_entry *rom = rom_first_file(region); rom != nullptr; rom = rom_next_file(rom)) { m_romstotal++; m_romstotalsize += rom_file_size(rom); } /* now process the entries in the region */ if (ROMREGION_ISROMDATA(region)) process_rom_entries(locationtag.c_str(), region, region + 1, &device, TRUE); else if (ROMREGION_ISDISKDATA(region)) process_disk_entries(regiontag.c_str(), region, region + 1, locationtag.c_str()); } /* now go back and post-process all the regions */ for (region = start_region; region != nullptr; region = rom_next_region(region)) { regiontag = device.subtag(ROMREGION_GETTAG(region)); region_post_process(regiontag.c_str(), ROMREGION_ISINVERTED(region)); } /* display the results and exit */ display_rom_load_results(TRUE); }
void rom_load_manager::process_disk_entries(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)) { auto chd = std::make_unique<open_chd>(regiontag); hash_collection hashes(ROM_GETHASHDATA(romp)); chd_error err; /* make the filename of the source */ std::string filename = std::string(ROM_GETNAME(romp)).append(".chd"); /* first open the source drive */ LOG(("Opening disk image: %s\n", filename.c_str())); err = chd_error(open_disk_image(machine().options(), &machine().system(), romp, chd->orig_chd(), locationtag)); if (err != CHDERR_NONE) { handle_missing_file(romp, std::string(), err); chd = nullptr; continue; } /* get the header and extract the SHA1 */ hash_collection acthashes; acthashes.add_sha1(chd->orig_chd().sha1()); /* verify the hash */ if (hashes != acthashes) { strcatprintf(m_errorstring, "%s WRONG CHECKSUMS:\n", filename.c_str()); dump_wrong_and_correct_checksums(hashes, acthashes); m_warnings++; } else if (hashes.flag(hash_collection::FLAG_BAD_DUMP)) { strcatprintf(m_errorstring, "%s CHD NEEDS REDUMP\n", filename.c_str()); m_knownbad++; } /* if not read-only, make the diff file */ if (!DISK_ISREADONLY(romp)) { /* try to open or create the diff */ err = open_disk_diff(machine().options(), romp, chd->orig_chd(), chd->diff_chd()); if (err != CHDERR_NONE) { strcatprintf(m_errorstring, "%s DIFF CHD ERROR: %s\n", filename.c_str(), chd_file::error_string(err)); m_errors++; chd = nullptr; continue; } } /* we're okay, add to the list of disks */ LOG(("Assigning to handle %d\n", DISK_GETINDEX(romp))); m_chd_list.push_back(std::move(chd)); } } }
media_auditor::summary media_auditor::summarize(const char *name, std::string *output) { if (m_record_list.count() == 0) { return NONE_NEEDED; } // loop over records summary overall_status = CORRECT; for (audit_record *record = m_record_list.first(); record != NULL; record = record->next()) { summary best_new_status = INCORRECT; // skip anything that's fine if (record->substatus() == audit_record::SUBSTATUS_GOOD) continue; // output the game name, file name, and length (if applicable) if (output != NULL) { strcatprintf(*output,"%-12s: %s", name, record->name()); if (record->expected_length() > 0) strcatprintf(*output," (%" I64FMT "d bytes)", record->expected_length()); strcatprintf(*output," - "); } // use the substatus for finer details switch (record->substatus()) { case audit_record::SUBSTATUS_GOOD_NEEDS_REDUMP: if (output != NULL) strcatprintf(*output,"NEEDS REDUMP\n"); best_new_status = BEST_AVAILABLE; break; case audit_record::SUBSTATUS_FOUND_NODUMP: if (output != NULL) strcatprintf(*output,"NO GOOD DUMP KNOWN\n"); best_new_status = BEST_AVAILABLE; break; case audit_record::SUBSTATUS_FOUND_BAD_CHECKSUM: if (output != NULL) { std::string tempstr; strcatprintf(*output,"INCORRECT CHECKSUM:\n"); strcatprintf(*output,"EXPECTED: %s\n", record->expected_hashes().macro_string(tempstr)); strcatprintf(*output," FOUND: %s\n", record->actual_hashes().macro_string(tempstr)); } break; case audit_record::SUBSTATUS_FOUND_WRONG_LENGTH: if (output != NULL) strcatprintf(*output,"INCORRECT LENGTH: %" I64FMT "d bytes\n", record->actual_length()); break; case audit_record::SUBSTATUS_NOT_FOUND: if (output != NULL) { device_t *shared_device = record->shared_device(); if (shared_device == NULL) strcatprintf(*output,"NOT FOUND\n"); else strcatprintf(*output,"NOT FOUND (%s)\n", shared_device->shortname()); } best_new_status = NOTFOUND; break; case audit_record::SUBSTATUS_NOT_FOUND_NODUMP: if (output != NULL) strcatprintf(*output,"NOT FOUND - NO GOOD DUMP KNOWN\n"); best_new_status = BEST_AVAILABLE; break; case audit_record::SUBSTATUS_NOT_FOUND_OPTIONAL: if (output != NULL) strcatprintf(*output,"NOT FOUND BUT OPTIONAL\n"); best_new_status = BEST_AVAILABLE; break; default: assert(false); } // downgrade the overall status if necessary overall_status = MAX(overall_status, best_new_status); } return overall_status; }
void info_xml_creator::output_rom(device_t &device) { // iterate over 3 different ROM "types": BIOS, ROMs, DISKs for (int rom_type = 0; rom_type < 3; rom_type++) for (const rom_entry *region = rom_first_region(device); region != NULL; region = rom_next_region(region)) { bool is_disk = ROMREGION_ISDISKDATA(region); // disk regions only work for disks if ((is_disk && rom_type != 2) || (!is_disk && rom_type == 2)) continue; // iterate through ROM entries for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom)) { bool is_bios = ROM_GETBIOSFLAGS(rom); const char *name = ROM_GETNAME(rom); int offset = ROM_GETOFFSET(rom); const char *merge_name = NULL; char bios_name[100]; // BIOS ROMs only apply to bioses if ((is_bios && rom_type != 0) || (!is_bios && rom_type == 0)) continue; // if we have a valid ROM and we are a clone, see if we can find the parent ROM hash_collection hashes(ROM_GETHASHDATA(rom)); if (!hashes.flag(hash_collection::FLAG_NO_DUMP)) merge_name = get_merge_name(hashes); if (&device != &m_drivlist.config().root_device()) merge_name = NULL; // scan for a BIOS name bios_name[0] = 0; if (!is_disk && is_bios) { // scan backwards through the ROM entries for (const rom_entry *brom = rom - 1; brom != m_drivlist.driver().rom; brom--) if (ROMENTRY_ISSYSTEM_BIOS(brom)) { strcpy(bios_name, ROM_GETNAME(brom)); break; } } std::string output; // opening tag if (!is_disk) output.append("\t\t<rom"); else output.append("\t\t<disk"); // add name, merge, bios, and size tags */ if (name != NULL && name[0] != 0) strcatprintf(output," name=\"%s\"", xml_normalize_string(name)); if (merge_name != NULL) strcatprintf(output," merge=\"%s\"", xml_normalize_string(merge_name)); if (bios_name[0] != 0) strcatprintf(output," bios=\"%s\"", xml_normalize_string(bios_name)); if (!is_disk) strcatprintf(output," size=\"%d\"", rom_file_size(rom)); // dump checksum information only if there is a known dump if (!hashes.flag(hash_collection::FLAG_NO_DUMP)) { // iterate over hash function types and print m_output their values std::string tempstr; strcatprintf(output," %s", hashes.attribute_string(tempstr)); } else output.append(" status=\"nodump\""); // append a region name strcatprintf(output," region=\"%s\"", ROMREGION_GETTAG(region)); // for non-disk entries, print offset if (!is_disk) strcatprintf(output," offset=\"%x\"", offset); // for disk entries, add the disk index else { strcatprintf(output," index=\"%x\"", DISK_GETINDEX(rom)); strcatprintf(output," writable=\"%s\"", DISK_ISREADONLY(rom) ? "no" : "yes"); } // add optional flag if (ROM_ISOPTIONAL(rom)) output.append(" optional=\"yes\""); output.append("/>\n"); fprintf(m_output, "%s", output.c_str()); } } }
void debug_view_breakpoints::view_update() { // Gather a list of all the breakpoints for all the CPUs gather_breakpoints(); // Set the view region so the scroll bars update m_total.x = tableBreaks[ARRAY_LENGTH(tableBreaks) - 1]; m_total.y = m_buffer.size() + 1; if (m_total.y < 10) m_total.y = 10; // Draw debug_view_char *dest = &m_viewdata[0]; std::string linebuf; // Header if (m_visible.y > 0) { linebuf.clear(); linebuf.append("ID"); if (m_sortType == &cIndexAscending) linebuf.push_back('\\'); else if (m_sortType == &cIndexDescending) linebuf.push_back('/'); pad_astring_to_length(linebuf, tableBreaks[0]); linebuf.append("En"); if (m_sortType == &cEnabledAscending) linebuf.push_back('\\'); else if (m_sortType == &cEnabledDescending) linebuf.push_back('/'); pad_astring_to_length(linebuf, tableBreaks[1]); linebuf.append("CPU"); if (m_sortType == &cCpuAscending) linebuf.push_back('\\'); else if (m_sortType == &cCpuDescending) linebuf.push_back('/'); pad_astring_to_length(linebuf, tableBreaks[2]); linebuf.append("Address"); if (m_sortType == &cAddressAscending) linebuf.push_back('\\'); else if (m_sortType == &cAddressDescending) linebuf.push_back('/'); pad_astring_to_length(linebuf, tableBreaks[3]); linebuf.append("Condition"); if (m_sortType == &cConditionAscending) linebuf.push_back('\\'); else if (m_sortType == &cConditionDescending) linebuf.push_back('/'); pad_astring_to_length(linebuf, tableBreaks[4]); linebuf.append("Action"); if (m_sortType == &cActionAscending) linebuf.push_back('\\'); else if (m_sortType == &cActionDescending) linebuf.push_back('/'); pad_astring_to_length(linebuf, tableBreaks[5]); for (UINT32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++) { dest->byte = (i < linebuf.length()) ? linebuf[i] : ' '; dest->attrib = DCA_ANCILLARY; } } for (int row = 1; row < m_visible.y; row++) { // Breakpoints int bpi = row + m_topleft.y - 1; if ((bpi < m_buffer.size()) && (bpi >= 0)) { device_debug::breakpoint *const bp = m_buffer[bpi]; linebuf.clear(); strcatprintf(linebuf, "%2X", bp->index()); pad_astring_to_length(linebuf, tableBreaks[0]); linebuf.push_back(bp->enabled() ? 'X' : 'O'); pad_astring_to_length(linebuf, tableBreaks[1]); linebuf.append(bp->debugInterface()->device().tag()); pad_astring_to_length(linebuf, tableBreaks[2]); linebuf.append(core_i64_hex_format(bp->address(), bp->debugInterface()->logaddrchars())); pad_astring_to_length(linebuf, tableBreaks[3]); if (strcmp(bp->condition(), "1")) linebuf.append(bp->condition()); pad_astring_to_length(linebuf, tableBreaks[4]); linebuf.append(bp->action()); pad_astring_to_length(linebuf, tableBreaks[5]); for (UINT32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++) { dest->byte = (i < linebuf.length()) ? linebuf[i] : ' '; dest->attrib = DCA_NORMAL; // Color disabled breakpoints red if ((i >= tableBreaks[0]) && (i < tableBreaks[1]) && !bp->enabled()) dest->attrib |= DCA_CHANGED; } } else { // Fill the remaining vertical space for (UINT32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++) { dest->byte = ' '; dest->attrib = DCA_NORMAL; } } } }
bool core_options::validate_and_set_data(core_options::entry &curentry, const char *newdata, int priority, std::string &error_string) { // trim any whitespace std::string data(newdata); strtrimspace(data); // trim quotes if (data.find_first_of('"') == 0 && data.find_last_of('"') == data.length() - 1) { data.erase(0, 1); data.erase(data.length() - 1, 1); } // validate the type of data and optionally the range float fval; int ival; switch (curentry.type()) { // booleans must be 0 or 1 case OPTION_BOOLEAN: if (sscanf(data.c_str(), "%d", &ival) != 1 || ival < 0 || ival > 1) { strcatprintf(error_string, "Illegal boolean value for %s: \"%s\"; reverting to %s\n", curentry.name(), data.c_str(), curentry.value()); return false; } break; // integers must be integral case OPTION_INTEGER: if (sscanf(data.c_str(), "%d", &ival) != 1) { strcatprintf(error_string, "Illegal integer value for %s: \"%s\"; reverting to %s\n", curentry.name(), data.c_str(), curentry.value()); return false; } if (curentry.has_range() && (ival < atoi(curentry.minimum()) || ival > atoi(curentry.maximum()))) { strcatprintf(error_string, "Out-of-range integer value for %s: \"%s\" (must be between %s and %s); reverting to %s\n", curentry.name(), data.c_str(), curentry.minimum(), curentry.maximum(), curentry.value()); return false; } break; // floating-point values must be numeric case OPTION_FLOAT: if (sscanf(data.c_str(), "%f", &fval) != 1) { strcatprintf(error_string, "Illegal float value for %s: \"%s\"; reverting to %s\n", curentry.name(), data.c_str(), curentry.value()); return false; } if (curentry.has_range() && ((double) fval < atof(curentry.minimum()) || (double) fval > atof(curentry.maximum()))) { strcatprintf(error_string, "Out-of-range float value for %s: \"%s\" (must be between %s and %s); reverting to %s\n", curentry.name(), data.c_str(), curentry.minimum(), curentry.maximum(), curentry.value()); return false; } break; // strings can be anything case OPTION_STRING: break; // anything else is invalid case OPTION_INVALID: case OPTION_HEADER: default: strcatprintf(error_string, "Attempted to set invalid option %s\n", curentry.name()); return false; } // set the data curentry.set_value(data.c_str(), priority); return true; }
void ram_device::device_validity_check(validity_checker &valid) const { const char *ramsize_string = NULL; int is_valid = FALSE; UINT32 specified_ram = 0; const char *gamename_option = NULL; /* verify default ram value */ if (default_size() == 0) osd_printf_error("Invalid default RAM option: %s\n", m_default_size); /* command line options are only parsed for the device named RAM_TAG */ if (tag() != NULL && strcmp(tag(), ":" RAM_TAG) == 0) { /* verify command line ram option */ ramsize_string = mconfig().options().ram_size(); gamename_option = mconfig().options().system_name(); if ((ramsize_string != NULL) && (ramsize_string[0] != '\0')) { specified_ram = parse_string(ramsize_string); if (specified_ram == 0) osd_printf_error("Cannot recognize the RAM option %s\n", ramsize_string); if (gamename_option != NULL && *gamename_option != 0 && strcmp(gamename_option, mconfig().gamedrv().name) == 0) { /* compare command line option to default value */ if (default_size() == specified_ram) is_valid = TRUE; /* verify extra ram options */ if (m_extra_options != NULL) { int j; int size = strlen(m_extra_options); char * const s = core_strdup(m_extra_options); char * const e = s + size; char *p = s; for (j=0;j<size;j++) { if (p[j]==',') p[j]=0; } /* try to parse each option */ while(p <= e) { UINT32 option_ram_size = parse_string(p); if (option_ram_size == 0) osd_printf_error("Invalid RAM option: %s\n", p); if (option_ram_size == specified_ram) is_valid = TRUE; p += strlen(p); if (p == e) break; p += 1; } osd_free(s); } } else { /* if not for this driver then return ok */ is_valid = TRUE; } } else { /* not specifying the ramsize on the command line is valid as well */ is_valid = TRUE; } } else is_valid = TRUE; if (!is_valid) { std::string output; strcatprintf(output, "Cannot recognize the RAM option %s", ramsize_string); strcatprintf(output, " (valid options are %s", m_default_size); if (m_extra_options != NULL) strcatprintf(output, ",%s).\n", m_extra_options); else strcatprintf(output, ").\n"); osd_printf_error("%s", output.c_str()); osd_printf_warning("Setting value to default %s\n",m_default_size); std::string error; mconfig().options().set_value(OPTION_RAMSIZE, m_default_size, OPTION_PRIORITY_CMDLINE, error); assert(error.empty()); } }
void real_profiler_state::update_text(running_machine &machine) { static const profile_string names[] = { { PROFILER_DRC_COMPILE, "DRC Compilation" }, { PROFILER_MEM_REMAP, "Memory Remapping" }, { PROFILER_MEMREAD, "Memory Read" }, { PROFILER_MEMWRITE, "Memory Write" }, { PROFILER_VIDEO, "Video Update" }, { PROFILER_DRAWGFX, "drawgfx" }, { PROFILER_COPYBITMAP, "copybitmap" }, { PROFILER_TILEMAP_DRAW, "Tilemap Draw" }, { PROFILER_TILEMAP_DRAW_ROZ, "Tilemap ROZ Draw" }, { PROFILER_TILEMAP_UPDATE, "Tilemap Update" }, { PROFILER_BLIT, "OSD Blitting" }, { PROFILER_SOUND, "Sound Generation" }, { PROFILER_TIMER_CALLBACK, "Timer Callbacks" }, { PROFILER_INPUT, "Input Processing" }, { PROFILER_MOVIE_REC, "Movie Recording" }, { PROFILER_LOGERROR, "Error Logging" }, { PROFILER_EXTRA, "Unaccounted/Overhead" }, { PROFILER_USER1, "User 1" }, { PROFILER_USER2, "User 2" }, { PROFILER_USER3, "User 3" }, { PROFILER_USER4, "User 4" }, { PROFILER_USER5, "User 5" }, { PROFILER_USER6, "User 6" }, { PROFILER_USER7, "User 7" }, { PROFILER_USER8, "User 8" }, { PROFILER_PROFILER, "Profiler" }, { PROFILER_IDLE, "Idle" } }; // compute the total time for all bits, not including profiler or idle UINT64 computed = 0; profile_type curtype; for (curtype = PROFILER_DEVICE_FIRST; curtype < PROFILER_PROFILER; ++curtype) computed += m_data[curtype]; // save that result in normalize, and continue adding the rest UINT64 normalize = computed; for ( ; curtype < PROFILER_TOTAL; ++curtype) computed += m_data[curtype]; // this becomes the total; if we end up with 0 for anything, we were just started, so return empty UINT64 total = computed; m_text.clear(); if (total == 0 || normalize == 0) { return; } // loop over all types and generate the string device_iterator iter(machine.root_device()); for (curtype = PROFILER_DEVICE_FIRST; curtype < PROFILER_TOTAL; ++curtype) { // determine the accumulated time for this type computed = m_data[curtype]; // if we have non-zero data and we're ready to display, do it if (computed != 0) { // start with the un-normalized percentage strcatprintf(m_text, "%02d%% ", (int)((computed * 100 + total / 2) / total)); // followed by the normalized percentage for everything but profiler and idle if (curtype < PROFILER_PROFILER) strcatprintf(m_text, "%02d%% ", (int)((computed * 100 + normalize / 2) / normalize)); // and then the text if (curtype >= PROFILER_DEVICE_FIRST && curtype <= PROFILER_DEVICE_MAX) strcatprintf(m_text, "'%s'", iter.byindex(curtype - PROFILER_DEVICE_FIRST)->tag().c_str()); else for (auto & name : names) if (name.type == curtype) { m_text.append(name.string); break; } // followed by a carriage return m_text.append("\n"); } } // reset data set to 0 memset(m_data, 0, sizeof(m_data)); }