Beispiel #1
0
const rom_entry *rom_next_file(const rom_entry *romp)
{
	romp++;
	while (!ROMENTRY_ISFILE(romp) && !ROMENTRY_ISREGIONEND(romp))
		romp++;
	return ROMENTRY_ISREGIONEND(romp) ? NULL : romp;
}
Beispiel #2
0
const rom_entry *rom_first_file(const rom_entry *romp)
{
	romp++;
	while (!ROMENTRY_ISFILE(romp) && !ROMENTRY_ISREGIONEND(romp))
		romp++;
	return ROMENTRY_ISREGIONEND(romp) ? nullptr : romp;
}
Beispiel #3
0
const struct RomModule *rom_next_file(const struct RomModule *romp)
{
	romp++;
	while (!ROMENTRY_ISFILE(romp) && !ROMENTRY_ISREGIONEND(romp))
		romp++;
	return ROMENTRY_ISREGIONEND(romp) ? NULL : romp;
}
Beispiel #4
0
/*-------------------------------------------------
    load_software - software image loading
-------------------------------------------------*/
bool legacy_image_device_base::load_software(char *swlist, char *swname, rom_entry *start)
{
	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))
			{
				UINT32 crc = 0;
				UINT8 crcbytes[4];
				file_error filerr;

				bool has_crc = hash_data_extract_binary_checksum(ROM_GETHASHDATA(romp), HASH_CRC, crcbytes);
				if (has_crc)
					crc = (crcbytes[0] << 24) | (crcbytes[1] << 16) | (crcbytes[2] << 8) | crcbytes[3];

				astring fname(swlist, PATH_SEPARATOR, swname, PATH_SEPARATOR, ROM_GETNAME(romp));
				if (has_crc)
					filerr = mame_fopen_crc(libretro_content_directory, fname, crc, OPEN_FLAG_READ, &m_mame_file);
				else
					filerr = mame_fopen(libretro_content_directory, fname, OPEN_FLAG_READ, &m_mame_file);

				if (filerr == FILERR_NONE)
				{
					m_file = mame_core_file(m_mame_file);
					retVal = TRUE;
				}
				break; // load first item for start
			}
			romp++;	/* something else; skip */
		}
	}
	return retVal;
}
/*-------------------------------------------------
    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;
}
Beispiel #6
0
static void process_rom_entries(romload_private *romdata, const char *regiontag, const rom_entry *parent_region, const rom_entry *romp, device_t *device, bool from_list)
{
	UINT32 lastflags = 0;

	/* loop until we hit the end of this region */
	while (!ROMENTRY_ISREGIONEND(romp))
	{
		/* if this is a continue entry, it's invalid */
		if (ROMENTRY_ISCONTINUE(romp))
			fatalerror("Error in RomModule definition: ROM_CONTINUE not preceded by ROM_LOAD\n");

		/* if this is an ignore entry, it's invalid */
		if (ROMENTRY_ISIGNORE(romp))
			fatalerror("Error in RomModule definition: ROM_IGNORE not preceded by ROM_LOAD\n");

		/* if this is a reload entry, it's invalid */
		if (ROMENTRY_ISRELOAD(romp))
			fatalerror("Error in RomModule definition: ROM_RELOAD not preceded by ROM_LOAD\n");

		/* handle fills */
		if (ROMENTRY_ISFILL(romp))
			fill_rom_data(romdata, romp++);

		/* handle copies */
		else if (ROMENTRY_ISCOPY(romp))
			copy_rom_data(romdata, romp++);

		/* handle files */
		else if (ROMENTRY_ISFILE(romp))
		{
			int irrelevantbios = (ROM_GETBIOSFLAGS(romp) != 0 && ROM_GETBIOSFLAGS(romp) != device->system_bios());
			const rom_entry *baserom = romp;
			int explength = 0;

			/* open the file if it is a non-BIOS or matches the current BIOS */
			LOG(("Opening ROM file: %s\n", ROM_GETNAME(romp)));
			astring tried_file_names;
			if (!irrelevantbios && !open_rom_file(romdata, regiontag, romp, tried_file_names, from_list))
				handle_missing_file(romdata, romp, tried_file_names, CHDERR_NONE);

			/* loop until we run out of reloads */
			do
			{
				/* loop until we run out of continues/ignores */
				do
				{
					rom_entry modified_romp = *romp++;
					//int readresult;

					/* handle flag inheritance */
					if (!ROM_INHERITSFLAGS(&modified_romp))
						lastflags = modified_romp._flags;
					else
						modified_romp._flags = (modified_romp._flags & ~ROM_INHERITEDFLAGS) | lastflags;

					explength += ROM_GETLENGTH(&modified_romp);

					/* attempt to read using the modified entry */
					if (!ROMENTRY_ISIGNORE(&modified_romp) && !irrelevantbios)
						/*readresult = */read_rom_data(romdata, parent_region, &modified_romp);
				}
				while (ROMENTRY_ISCONTINUE(romp) || ROMENTRY_ISIGNORE(romp));

				/* if this was the first use of this file, verify the length and CRC */
				if (baserom)
				{
					LOG(("Verifying length (%X) and checksums\n", explength));
					verify_length_and_hash(romdata, ROM_GETNAME(baserom), explength, hash_collection(ROM_GETHASHDATA(baserom)));
					LOG(("Verify finished\n"));
				}

				/* reseek to the start and clear the baserom so we don't reverify */
				if (romdata->file != NULL)
					romdata->file->seek(0, SEEK_SET);
				baserom = NULL;
				explength = 0;
			}
			while (ROMENTRY_ISRELOAD(romp));

			/* close the file */
			if (romdata->file != NULL)
			{
				LOG(("Closing ROM file\n"));
				global_free(romdata->file);
				romdata->file = NULL;
			}
		}
		else
		{
			romp++; /* something else; skip */
		}
	}
}
Beispiel #7
0
static void process_disk_entries(romload_private *romdata, 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))
		{
			open_chd *chd = global_alloc(open_chd(regiontag));

			hash_collection hashes(ROM_GETHASHDATA(romp));
			chd_error err;

			/* make the filename of the source */
			astring filename(ROM_GETNAME(romp), ".chd");

			/* first open the source drive */
			LOG(("Opening disk image: %s\n", filename.cstr()));
			err = chd_error(open_disk_image(romdata->machine().options(), &romdata->machine().system(), romp, chd->orig_chd(), locationtag));
			if (err != CHDERR_NONE)
			{
				handle_missing_file(romdata, romp, astring(), err);
				global_free(chd);
				continue;
			}

			/* get the header and extract the SHA1 */
			hash_collection acthashes;
			acthashes.add_sha1(chd->orig_chd().sha1());

			/* verify the hash */
			if (hashes != acthashes)
			{
				romdata->errorstring.catprintf("%s WRONG CHECKSUMS:\n", filename.cstr());
				dump_wrong_and_correct_checksums(romdata, hashes, acthashes);
				romdata->warnings++;
			}
			else if (hashes.flag(hash_collection::FLAG_BAD_DUMP))
			{
				romdata->errorstring.catprintf("%s CHD NEEDS REDUMP\n", filename.cstr());
				romdata->knownbad++;
			}

			/* if not read-only, make the diff file */
			if (!DISK_ISREADONLY(romp))
			{
				/* try to open or create the diff */
				err = open_disk_diff(romdata->machine().options(), romp, chd->orig_chd(), chd->diff_chd());
				if (err != CHDERR_NONE)
				{
					romdata->errorstring.catprintf("%s DIFF CHD ERROR: %s\n", filename.cstr(), chd_file::error_string(err));
					romdata->errors++;
					global_free(chd);
					continue;
				}
			}

			/* we're okay, add to the list of disks */
			LOG(("Assigning to handle %d\n", DISK_GETINDEX(romp)));
			romdata->machine().romload_data->chd_list.append(*chd);
		}
	}
}
Beispiel #8
0
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));
		}
	}
}
Beispiel #9
0
bool device_image_interface::load_software(software_list_device &swlist, const char *swname, const rom_entry *start)
{
	std::string locationtag, breakstr("%");
	const rom_entry *region;
	bool retVal = false;
	int warningcount = 0;
	for (region = start; region != nullptr; 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))
			{
				osd_file::error filerr = osd_file::error::NOT_FOUND;

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

				const software_info *swinfo = swlist.find(swname);
				if (swinfo == nullptr)
					return false;

				UINT32 supported = swinfo->supported();
				if (supported == SOFTWARE_SUPPORTED_PARTIAL)
					osd_printf_error("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist.list_name().c_str());
				if (supported == SOFTWARE_SUPPORTED_NO)
					osd_printf_error("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist.list_name().c_str());

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

				while (swinfo != nullptr)
				{
					locationtag.append(swinfo->shortname()).append(breakstr);
					swinfo = !swinfo->parentname().empty() ? swlist.find(swinfo->parentname().c_str()) : nullptr;
				}
				// strip the final '%'
				locationtag.erase(locationtag.length() - 1, 1);


				// check if locationtag actually contains two locations separated by '%'
				// (i.e. check if we are dealing with a clone in softwarelist)
				std::string tag2, tag3, tag4(locationtag), tag5;
				int separator = tag4.find_first_of('%');
				if (separator != -1)
				{
					// we are loading a clone through softlists, split the setname from the parentname
					tag5.assign(tag4.substr(separator + 1, tag4.length() - separator + 1));
					tag4.erase(separator, tag4.length() - separator);
				}

				// prepare locations where we have to load from: list/parentname & list/clonename
				std::string tag1(swlist.list_name());
				tag1.append(PATH_SEPARATOR);
				tag2.assign(tag1.append(tag4));
				tag1.assign(swlist.list_name());
				tag1.append(PATH_SEPARATOR);
				tag3.assign(tag1.append(tag5));

				if (tag5.find_first_of('%') != -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 == nullptr) && (tag2.c_str() != nullptr))
					m_mame_file = common_process_file(device().machine().options(), tag2.c_str(), has_crc, crc, romp, filerr);
				// try to load from list/parentname
				if ((m_mame_file == nullptr) && (tag3.c_str() != nullptr))
					m_mame_file = common_process_file(device().machine().options(), tag3.c_str(), has_crc, crc, romp, filerr);
				// try to load from setname
				if ((m_mame_file == nullptr) && (tag4.c_str() != nullptr))
					m_mame_file = common_process_file(device().machine().options(), tag4.c_str(), has_crc, crc, romp, filerr);
				// try to load from parentname
				if ((m_mame_file == nullptr) && (tag5.c_str() != nullptr))
					m_mame_file = common_process_file(device().machine().options(), tag5.c_str(), has_crc, crc, romp, filerr);

				warningcount += verify_length_and_hash(m_mame_file.get(),ROM_GETNAME(romp),ROM_GETLENGTH(romp), util::hash_collection(ROM_GETHASHDATA(romp)));

				if (filerr == osd_file::error::NONE)
					filerr = util::core_file::open_proxy(*m_mame_file, m_file);
				if (filerr == osd_file::error::NONE)
					retVal = true;

				break; // load first item for start
			}
			romp++; /* something else; skip */
		}
	}
	if (warningcount > 0)
	{
		osd_printf_error("WARNING: the software item might not run correctly.\n");
	}
	return retVal;
}
Beispiel #10
0
const struct RomModule *rom_first_chunk(const struct RomModule *romp)
{
	return (ROMENTRY_ISFILE(romp)) ? romp : NULL;
}
Beispiel #11
0
static int process_disk_entries(struct rom_load_data *romdata, const struct RomModule *romp)
{
	/* loop until we hit the end of this region */
	while (!ROMENTRY_ISREGIONEND(romp))
	{
		/* handle files */
		if (ROMENTRY_ISFILE(romp))
		{
			struct chd_file *source, *diff = NULL;
			struct chd_header header;
			char filename[1024], *c;
			char acthash[HASH_BUF_SIZE];
			int err;

			/* make the filename of the source */
			strcpy(filename, ROM_GETNAME(romp));
			c = strrchr(filename, '.');
			if (c)
				strcpy(c, ".chd");
			else
				strcat(filename, ".chd");

			/* first open the source drive */
			debugload("Opening disk image: %s\n", filename);
			source = chd_open(filename, 0, NULL);
			if (!source)
			{
				if (chd_get_last_error() == CHDERR_UNSUPPORTED_VERSION)
					sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s UNSUPPORTED CHD VERSION\n", filename);
				else
					sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s NOT FOUND\n", filename);
				romdata->errors++;
				romp++;
				continue;
			}

			/* get the header and extract the MD5/SHA1 */
			header = *chd_get_header(source);
			hash_data_clear(acthash);
			hash_data_insert_binary_checksum(acthash, HASH_MD5, header.md5);
			hash_data_insert_binary_checksum(acthash, HASH_SHA1, header.sha1);

			/* verify the MD5 */
			if (!hash_data_is_equal(ROM_GETHASHDATA(romp), acthash, 0))
			{
				sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s WRONG CHECKSUMS:\n", filename);
				dump_wrong_and_correct_checksums(romdata, ROM_GETHASHDATA(romp), acthash);
				romdata->warnings++;
			}

			/* if not read-only, make the diff file */
			if (!DISK_ISREADONLY(romp))
			{
				/* make the filename of the diff */
				strcpy(filename, ROM_GETNAME(romp));
				c = strrchr(filename, '.');
				if (c)
					strcpy(c, ".dif");
				else
					strcat(filename, ".dif");

				/* try to open the diff */
				debugload("Opening differencing image: %s\n", filename);
				diff = chd_open(filename, 1, source);
				if (!diff)
				{
					/* didn't work; try creating it instead */
					debugload("Creating differencing image: %s\n", filename);
					err = chd_create(filename, 0, 0, CHDCOMPRESSION_NONE, source);
					if (err != CHDERR_NONE)
					{
						if (chd_get_last_error() == CHDERR_UNSUPPORTED_VERSION)
							sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s UNSUPPORTED CHD VERSION\n", filename);
						else
							sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s: CAN'T CREATE DIFF FILE\n", filename);
						romdata->errors++;
						romp++;
						continue;
					}

					/* open the newly-created diff file */
					debugload("Opening differencing image: %s\n", filename);
					diff = chd_open(filename, 1, source);
					if (!diff)
					{
						if (chd_get_last_error() == CHDERR_UNSUPPORTED_VERSION)
							sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s UNSUPPORTED CHD VERSION\n", filename);
						else
							sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%-12s: CAN'T OPEN DIFF FILE\n", filename);
						romdata->errors++;
						romp++;
						continue;
					}
				}
			}

			/* we're okay, set the handle */
			debugload("Assigning to handle %d\n", DISK_GETINDEX(romp));
			disk_handle[DISK_GETINDEX(romp)] = DISK_ISREADONLY(romp) ? source : diff;
			romp++;
		}
	}
	return 1;
}
Beispiel #12
0
static int process_rom_entries(struct rom_load_data *romdata, const struct RomModule *romp)
{
	UINT32 lastflags = 0;

	/* loop until we hit the end of this region */
	while (!ROMENTRY_ISREGIONEND(romp))
	{
		/* if this is a continue entry, it's invalid */
		if (ROMENTRY_ISCONTINUE(romp))
		{
			printf("Error in RomModule definition: ROM_CONTINUE not preceded by ROM_LOAD\n");
			goto fatalerror;
		}

		/* if this is a reload entry, it's invalid */
		if (ROMENTRY_ISRELOAD(romp))
		{
			printf("Error in RomModule definition: ROM_RELOAD not preceded by ROM_LOAD\n");
			goto fatalerror;
		}

		/* handle fills */
		if (ROMENTRY_ISFILL(romp))
		{
			if (!fill_rom_data(romdata, romp++))
				goto fatalerror;
		}

		/* handle copies */
		else if (ROMENTRY_ISCOPY(romp))
		{
			if (!copy_rom_data(romdata, romp++))
				goto fatalerror;
		}

		/* handle files */
		else if (ROMENTRY_ISFILE(romp))
		{
			if (!ROM_GETBIOSFLAGS(romp) || (ROM_GETBIOSFLAGS(romp) == (system_bios+1))) /* alternate bios sets */
			{
				const struct RomModule *baserom = romp;
				int explength = 0;

				/* open the file */
				debugload("Opening ROM file: %s\n", ROM_GETNAME(romp));
				if (!open_rom_file(romdata, romp))
					handle_missing_file(romdata, romp);

				/* loop until we run out of reloads */
				do
				{
					/* loop until we run out of continues */
					do
					{
						struct RomModule modified_romp = *romp++;
						int readresult;

						/* handle flag inheritance */
						if (!ROM_INHERITSFLAGS(&modified_romp))
							lastflags = modified_romp._flags;
						else
							modified_romp._flags = (modified_romp._flags & ~ROM_INHERITEDFLAGS) | lastflags;

						explength += ROM_GETLENGTH(&modified_romp);

						/* attempt to read using the modified entry */
						readresult = read_rom_data(romdata, &modified_romp);
						if (readresult == -1)
							goto fatalerror;
					}
					while (ROMENTRY_ISCONTINUE(romp));

					/* if this was the first use of this file, verify the length and CRC */
					if (baserom)
					{
						debugload("Verifying length (%X) and checksums\n", explength);
						verify_length_and_hash(romdata, ROM_GETNAME(baserom), explength, ROM_GETHASHDATA(baserom));
						debugload("Verify finished\n");
					}

					/* reseek to the start and clear the baserom so we don't reverify */
					if (romdata->file)
						mame_fseek(romdata->file, 0, SEEK_SET);
					baserom = NULL;
					explength = 0;
				}
				while (ROMENTRY_ISRELOAD(romp));

				/* close the file */
				if (romdata->file)
				{
					debugload("Closing ROM file\n");
					mame_fclose(romdata->file);
					romdata->file = NULL;
				}
			}
			else
			{
				romp++; /* skip over file */
			}
		}
	}
	return 1;

	/* error case */
fatalerror:
	if (romdata->file)
		mame_fclose(romdata->file);
	romdata->file = NULL;
	return 0;
}
Beispiel #13
0
static void process_disk_entries(rom_load_data *romdata, const rom_entry *romp)
{
	/* loop until we hit the end of this region */
	while (!ROMENTRY_ISREGIONEND(romp))
	{
		/* handle files */
		if (ROMENTRY_ISFILE(romp))
		{
			chd_file *source, *diff = NULL;
			chd_header header;
			char filename[1024];
			char acthash[HASH_BUF_SIZE];
			chd_error err;

			/* make the filename of the source */
			sprintf(filename, "%s.chd", ROM_GETNAME(romp));

			/* first open the source drive */
			debugload("Opening disk image: %s\n", filename);
			err = open_disk_image(Machine->gamedrv, romp, &source);
			if (err != CHDERR_NONE)
			{
				if (err == CHDERR_UNSUPPORTED_VERSION)
					sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s UNSUPPORTED CHD VERSION\n", filename);
				else
					sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s NOT FOUND\n", filename);

				/* if this is NO_DUMP, keep going, though the system may not be able to handle it */
				if (hash_data_has_info(ROM_GETHASHDATA(romp), HASH_INFO_NO_DUMP))
					romdata->warnings++;
				else
					romdata->errors++;
				romp++;
				continue;
			}

			/* get the header and extract the MD5/SHA1 */
			header = *chd_get_header(source);
			hash_data_clear(acthash);
			hash_data_insert_binary_checksum(acthash, HASH_MD5, header.md5);
			hash_data_insert_binary_checksum(acthash, HASH_SHA1, header.sha1);

			/* verify the MD5 */
			if (!hash_data_is_equal(ROM_GETHASHDATA(romp), acthash, 0))
			{
				sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s WRONG CHECKSUMS:\n", filename);
				dump_wrong_and_correct_checksums(romdata, ROM_GETHASHDATA(romp), acthash);
				romdata->warnings++;
			}
			else if (hash_data_has_info(ROM_GETHASHDATA(romp), HASH_INFO_BAD_DUMP))
			{
				sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s CHD NEEDS REDUMP\n", filename);
				romdata->warnings++;
			}

			/* if not read-only, make the diff file */
			if (!DISK_ISREADONLY(romp))
			{
				/* make the filename of the diff */
				sprintf(filename, "%s.dif", ROM_GETNAME(romp));

				/* try to open the diff */
				debugload("Opening differencing image: %s\n", filename);
				err = chd_open(filename, CHD_OPEN_READWRITE, source, &diff);
				if (err != CHDERR_NONE)
				{
					/* didn't work; try creating it instead */
					debugload("Creating differencing image: %s\n", filename);
					err = chd_create(filename, 0, 0, CHDCOMPRESSION_NONE, source);
					if (err != CHDERR_NONE)
					{
						if (err == CHDERR_UNSUPPORTED_VERSION)
							sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s UNSUPPORTED CHD VERSION\n", filename);
						else
							sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s: CAN'T CREATE DIFF FILE\n", filename);
						romdata->errors++;
						romp++;
						continue;
					}

					/* open the newly-created diff file */
					debugload("Opening differencing image: %s\n", filename);
					err = chd_open(filename, CHD_OPEN_READWRITE, source, &diff);
					if (err != CHDERR_NONE)
					{
						if (err == CHDERR_UNSUPPORTED_VERSION)
							sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s UNSUPPORTED CHD VERSION\n", filename);
						else
							sprintf(&romdata->errorbuf[strlen(romdata->errorbuf)], "%s: CAN'T OPEN DIFF FILE\n", filename);
						romdata->errors++;
						romp++;
						continue;
					}
				}
			}

			/* we're okay, set the handle */
			debugload("Assigning to handle %d\n", DISK_GETINDEX(romp));
			disk_handle[DISK_GETINDEX(romp)] = DISK_ISREADONLY(romp) ? source : diff;
			romp++;
		}
	}
}
Beispiel #14
0
const rom_entry *rom_first_chunk(const rom_entry *romp)
{
	return (ROMENTRY_ISFILE(romp)) ? romp : NULL;
}
Beispiel #15
0
static int info_listsoftware(core_options *options, const char *gamename)
{
	FILE *out = stdout;
	int nr_lists = 0;
	char ** lists = NULL;
	int list_idx = 0;

	/* First determine the maximum number of lists we might encounter */
	for ( int drvindex = 0; drivers[drvindex] != NULL; drvindex++ )
	{
		if ( mame_strwildcmp( gamename, drivers[drvindex]->name ) == 0 )
		{
			/* allocate the machine config */
			machine_config *config = global_alloc(machine_config(drivers[drvindex]->machine_config));

			for (const device_config *dev = config->m_devicelist.first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
			{
				software_list_config *swlist = (software_list_config *)downcast<const legacy_device_config_base *>(dev)->inline_config();

				for ( int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++ )
				{
					if ( swlist->list_name[i] && *swlist->list_name[i]  && (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM))
						nr_lists++;
				}
			}

			/* free the machine config */
			global_free(config);
		}
	}

	lists = global_alloc_array( char *, nr_lists );

	fprintf( out,
			"<?xml version=\"1.0\"?>\n"
			"<!DOCTYPE softwarelist [\n"
			"<!ELEMENT softwarelists (softwarelist*)>\n"
			"\t<!ELEMENT softwarelist (software+)>\n"
			"\t\t<!ATTLIST softwarelist name CDATA #REQUIRED>\n"
			"\t\t<!ATTLIST softwarelist description CDATA #IMPLIED>\n"
			"\t\t<!ELEMENT software (description, year?, publisher, part*)>\n"
			"\t\t\t<!ATTLIST software name CDATA #REQUIRED>\n"
			"\t\t\t<!ATTLIST software cloneof CDATA #IMPLIED>\n"
			"\t\t\t<!ATTLIST software supported (yes|partial|no) \"yes\">\n"
			"\t\t\t<!ELEMENT description (#PCDATA)>\n"
			"\t\t\t<!ELEMENT year (#PCDATA)>\n"
			"\t\t\t<!ELEMENT publisher (#PCDATA)>\n"
			"\t\t\t<!ELEMENT part (dataarea*)>\n"
			"\t\t\t\t<!ATTLIST part name CDATA #REQUIRED>\n"
			"\t\t\t\t<!ATTLIST part interface CDATA #REQUIRED>\n"
			"\t\t\t\t<!ATTLIST part feature CDATA #IMPLIED>\n"
			"\t\t\t\t<!ELEMENT dataarea (rom*)>\n"
			"\t\t\t\t\t<!ATTLIST dataarea name CDATA #REQUIRED>\n"
			"\t\t\t\t\t<!ATTLIST dataarea size CDATA #REQUIRED>\n"
			"\t\t\t\t\t<!ATTLIST dataarea databits (8|16|32|64) \"8\">\n"
			"\t\t\t\t\t<!ATTLIST dataarea endian (big|little) \"little\">\n"
			"\t\t\t\t\t<!ELEMENT rom EMPTY>\n"
			"\t\t\t\t\t\t<!ATTLIST rom name CDATA #IMPLIED>\n"
			"\t\t\t\t\t\t<!ATTLIST rom size CDATA #REQUIRED>\n"
			"\t\t\t\t\t\t<!ATTLIST rom crc CDATA #IMPLIED>\n"
			"\t\t\t\t\t\t<!ATTLIST rom md5 CDATA #IMPLIED>\n"
			"\t\t\t\t\t\t<!ATTLIST rom sha1 CDATA #IMPLIED>\n"
			"\t\t\t\t\t\t<!ATTLIST rom offset CDATA #IMPLIED>\n"
			"\t\t\t\t\t\t<!ATTLIST rom status (baddump|nodump|good) \"good\">\n"
			"\t\t\t\t\t\t<!ATTLIST rom loadflag (load16_byte|load16_word|load16_word_swap|load32_byte|load32_word|load32_word_swap|load32_dword|load64_word|load64_word_swap|reload) #IMPLIED>\n"
			"]>\n\n"
			"<softwarelists>\n"
	);

	for ( int drvindex = 0; drivers[drvindex] != NULL; drvindex++ )
	{
		if ( mame_strwildcmp( gamename, drivers[drvindex]->name ) == 0 )
		{
			/* allocate the machine config */
			machine_config *config = global_alloc(machine_config(drivers[drvindex]->machine_config));

			for (const device_config *dev = config->m_devicelist.first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
			{
				software_list_config *swlist = (software_list_config *)downcast<const legacy_device_config_base *>(dev)->inline_config();

				for ( int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++ )
				{
					if ( swlist->list_name[i] && *swlist->list_name[i] && (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM))
					{
						software_list *list = software_list_open( options, swlist->list_name[i], FALSE, NULL );

						if ( list )
						{
							/* Verify if we have encountered this list before */
							bool seen_before = false;
							for ( int l = 0; l < list_idx && !seen_before; l++ )
							{
								if ( ! strcmp( swlist->list_name[i], lists[l] ) )
								{
									seen_before = true;
								}
							}

							if ( ! seen_before )
							{
								lists[list_idx] = core_strdup( swlist->list_name[i] );
								list_idx++;

								fprintf(out, "\t<softwarelist name=\"%s\">\n", swlist->list_name[i] );

								for ( software_info *swinfo = software_list_find( list, "*", NULL ); swinfo != NULL; swinfo = software_list_find( list, "*", swinfo ) )
								{
									fprintf( out, "\t\t<software name=\"%s\"", swinfo->shortname );
									if ( swinfo->parentname != NULL )
										fprintf( out, " cloneof=\"%s\"", swinfo->parentname );
									if ( swinfo->supported == SOFTWARE_SUPPORTED_PARTIAL )
										fprintf( out, " supported=\"partial\"" );
									if ( swinfo->supported == SOFTWARE_SUPPORTED_NO )
										fprintf( out, " supported=\"no\"" );
									fprintf( out, ">\n" );
									fprintf( out, "\t\t\t<description>%s</description>\n", xml_normalize_string(swinfo->longname) );
									fprintf( out, "\t\t\t<year>%s</year>\n", xml_normalize_string( swinfo->year ) );
									fprintf( out, "\t\t\t<publisher>%s</publisher>\n", xml_normalize_string( swinfo->publisher ) );

									for ( software_part *part = software_find_part( swinfo, NULL, NULL ); part != NULL; part = software_part_next( part ) )
									{
										fprintf( out, "\t\t\t<part name=\"%s\"", part->name );
										if ( part->interface_ )
											fprintf( out, " interface=\"%s\"", part->interface_ );
//                                          if ( part->feature )
//                                              fprintf( out, " features=\"%s\"", part->feature );
										fprintf( out, ">\n");

										/* TODO: display rom region information */
										for ( const rom_entry *region = part->romdata; region; region = rom_next_region( region ) )
										{
											fprintf( out, "\t\t\t\t<dataarea name=\"%s\" size=\"%x\">\n", ROMREGION_GETTAG(region), ROMREGION_GETLENGTH(region) );

											for ( const rom_entry *rom = rom_first_file( region ); rom && !ROMENTRY_ISREGIONEND(rom); rom++ )
											{
												if ( ROMENTRY_ISFILE(rom) )
												{
													fprintf( out, "\t\t\t\t\t<rom name=\"%s\" size=\"%d\"", xml_normalize_string(ROM_GETNAME(rom)), rom_file_size(rom) );

													/* dump checksum information only if there is a known dump */
													if (!hash_data_has_info(ROM_GETHASHDATA(rom), HASH_INFO_NO_DUMP))
													{
														char checksum[HASH_BUF_SIZE];
														int hashtype;

														/* iterate over hash function types and print out their values */
														for (hashtype = 0; hashtype < HASH_NUM_FUNCTIONS; hashtype++)
															if (hash_data_extract_printable_checksum(ROM_GETHASHDATA(rom), 1 << hashtype, checksum))
																fprintf(out, " %s=\"%s\"", hash_function_name(1 << hashtype), checksum);
													}

													fprintf( out, " offset=\"%x\"", ROM_GETOFFSET(rom) );

													if ( hash_data_has_info(ROM_GETHASHDATA(rom), HASH_INFO_BAD_DUMP) )
														fprintf( out, " status=\"baddump\"" );
													if ( hash_data_has_info(ROM_GETHASHDATA(rom), HASH_INFO_NO_DUMP) )
														fprintf( out, " status=\"nodump\"" );

													fprintf( out, "/>\n" );
												}
												else if ( ROMENTRY_ISRELOAD(rom) )
												{
													fprintf( out, "\t\t\t\t\t<rom size=\"%d\" offset=\"%x\" loadflag=\"reload\" />\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) );
												}
											}

											fprintf( out, "\t\t\t\t</dataarea>\n" );
										}

										fprintf( out, "\t\t\t</part>\n" );
									}

									fprintf( out, "\t\t</software>\n" );
								}

								fprintf(out, "\t</softwarelist>\n" );
							}

							software_list_close( list );
						}
					}
				}
			}

			global_free(config);
		}
	}

	fprintf( out, "</softwarelists>\n" );

	global_free( lists );

	return MAMERR_NONE;
}