/*-------------------------------------------------
    load_software - software image loading
-------------------------------------------------*/
bool device_image_interface::load_software(char *swlist, char *swname, rom_entry *start)
{
	astring locationtag, breakstr("%");
	const rom_entry *region;
	astring regiontag;
	bool retVal = FALSE;
	for (region = start; region != NULL; region = rom_next_region(region))
	{
		/* loop until we hit the end of this region */
		const rom_entry *romp = region + 1;
		while (!ROMENTRY_ISREGIONEND(romp))
		{
			/* handle files */
			if (ROMENTRY_ISFILE(romp))
			{
				file_error filerr = FILERR_NOT_FOUND;

				UINT32 crc = 0;
				bool has_crc = hash_collection(ROM_GETHASHDATA(romp)).crc(crc);

				// attempt reading up the chain through the parents and create a locationtag astring in the format
				// " swlist % clonename % parentname "
				// below, we have the code to split the elements and to create paths to load from

				software_list *software_list_ptr = software_list_open(device().machine().options(), swlist, FALSE, NULL);
				if (software_list_ptr)
				{
					for (software_info *swinfo = software_list_find(software_list_ptr, swname, NULL); swinfo != NULL; )
					{
						{
							astring tmp(swinfo->shortname);
							locationtag.cat(tmp);
							locationtag.cat(breakstr);
							//printf("%s\n", locationtag.cstr());
						}

						const char *parentname = software_get_clone(device().machine().options(), swlist, swinfo->shortname);
						if (parentname != NULL)
							swinfo = software_list_find(software_list_ptr, parentname, NULL);
						else
							swinfo = NULL;
					}
					// strip the final '%'
					locationtag.del(locationtag.len() - 1, 1);
					software_list_close(software_list_ptr);
				}

				if (software_get_support(device().machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_PARTIAL)
					mame_printf_error("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist);

				if (software_get_support(device().machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_NO)
					mame_printf_error("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist);

				// check if locationtag actually contains two locations separated by '%'
				// (i.e. check if we are dealing with a clone in softwarelist)
				astring tag2, tag3, tag4(locationtag), tag5;
				int separator = tag4.chr(0, '%');
				if (separator != -1)
				{
					// we are loading a clone through softlists, split the setname from the parentname
					tag5.cpysubstr(tag4, separator + 1, tag4.len() - separator + 1);
					tag4.del(separator, tag4.len() - separator);
				}

				// prepare locations where we have to load from: list/parentname & list/clonename
				astring tag1(swlist);
				tag1.cat(PATH_SEPARATOR);
				tag2.cpy(tag1.cat(tag4));
				tag1.cpy(swlist);
				tag1.cat(PATH_SEPARATOR);
				tag3.cpy(tag1.cat(tag5));

				if (tag5.chr(0, '%') != -1)
					fatalerror("We do not support clones of clones!\n");

				// try to load from the available location(s):
				// - if we are not using lists, we have regiontag only;
				// - if we are using lists, we have: list/clonename, list/parentname, clonename, parentname
				// try to load from list/setname
				if ((m_mame_file == NULL) && (tag2.cstr() != NULL))
					filerr = common_process_file(device().machine().options(), tag2.cstr(), has_crc, crc, romp, &m_mame_file);
				// try to load from list/parentname
				if ((m_mame_file == NULL) && (tag3.cstr() != NULL))
					filerr = common_process_file(device().machine().options(), tag3.cstr(), has_crc, crc, romp, &m_mame_file);
				// try to load from setname
				if ((m_mame_file == NULL) && (tag4.cstr() != NULL))
					filerr = common_process_file(device().machine().options(), tag4.cstr(), has_crc, crc, romp, &m_mame_file);
				// try to load from parentname
				if ((m_mame_file == NULL) && (tag5.cstr() != NULL))
					filerr = common_process_file(device().machine().options(), tag5.cstr(), has_crc, crc, romp, &m_mame_file);

				if (filerr == FILERR_NONE)
				{
					m_file = *m_mame_file;
					retVal = TRUE;
				}

				break; // load first item for start
			}
			romp++;	/* something else; skip */
		}
	}
	return retVal;
}
示例#2
0
void load_software_part_region(device_t *device, char *swlist, char *swname, rom_entry *start_region)
{
	astring locationtag(swlist), breakstr("%");
	rom_load_data *romdata = device->machine().romload_data;
	const rom_entry *region;
	astring regiontag;

	// attempt reading up the chain through the parents and create a locationtag astring in the format
	// " swlist % clonename % parentname "
	// open_rom_file contains the code to split the elements and to create paths to load from

	software_list *software_list_ptr = software_list_open(device->machine().options(), swlist, FALSE, NULL);
	if (software_list_ptr)
	{
		locationtag.cat(breakstr);

		for (software_info *swinfo = software_list_find(software_list_ptr, swname, NULL); swinfo != NULL; )
		{
			{
				astring tmp(swinfo->shortname);
				locationtag.cat(tmp);
				locationtag.cat(breakstr);
				// printf("%s\n", locationtag.cstr());
			}
			const char *parentname = software_get_clone(device->machine().options(), swlist, swinfo->shortname);
			if (parentname != NULL)
				swinfo = software_list_find(software_list_ptr, parentname, NULL);
			else
				swinfo = NULL;
		}
		// strip the final '%'
		locationtag.del(locationtag.len() - 1, 1);
		software_list_close(software_list_ptr);
	}

	/* Make sure we are passed a device */
	assert(device != NULL);

	romdata->errorstring.reset();
	romdata->softwarningstring.reset();

	if (software_get_support(device->machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_PARTIAL)
	{
		romdata->errorstring.catprintf("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist);
		romdata->softwarningstring.catprintf("Support for software %s (in list %s) is only partial\n", swname, swlist);
	}
	if (software_get_support(device->machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_NO)
	{
		romdata->errorstring.catprintf("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist);
		romdata->softwarningstring.catprintf("Support for software %s (in list %s) is only preliminary\n", swname, swlist);
	}

	/* loop until we hit the end */
	for (region = start_region; region != NULL; region = rom_next_region(region))
	{
		UINT32 regionlength = ROMREGION_GETLENGTH(region);

		device->subtag(regiontag, ROMREGION_GETTAG(region));
		LOG(("Processing region \"%s\" (length=%X)\n", regiontag.cstr(), 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 = romdata->machine().root_device().memregion(regiontag);
		if (memregion != NULL)
		{
			if (romdata->machine().device(regiontag) != NULL)
				normalize_flags_for_device(romdata->machine(), regiontag, width, endianness);

			/* clear old region (todo: should be moved to an image unload function) */
			romdata->machine().memory().region_free(memregion->name());
		}

		/* 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 */
		if (ROMREGION_ISROMDATA(region))
			process_rom_entries(romdata, locationtag, region, region + 1);
		else if (ROMREGION_ISDISKDATA(region))
			process_disk_entries(romdata, core_strdup(regiontag.cstr()), region, region + 1, locationtag);
	}

	/* now go back and post-process all the regions */
	for (region = start_region; region != NULL; region = rom_next_region(region)) {
		device->subtag(regiontag, ROMREGION_GETTAG(region));
		region_post_process(romdata, regiontag.cstr(), ROMREGION_ISINVERTED(region));
	}

	/* display the results and exit */
	display_rom_load_results(romdata);
}