Exemple #1
0
static void identify_data(const char *name, const UINT8 *data, int length, romident_status *status)
{
	char hash[HASH_BUF_SIZE];
	UINT8 *tempjed = NULL;
	astring *basename;
	int found = 0;
	jed_data jed;

	/* if this is a '.jed' file, process it into raw bits first */
	if (core_filename_ends_with(name, ".jed") && jed_parse(data, length, &jed) == JEDERR_NONE)
	{
		/* now determine the new data length and allocate temporary memory for it */
		length = jedbin_output(&jed, NULL, 0);
		tempjed = malloc(length);
		if (tempjed == NULL)
			return;

		/* create a binary output of the JED data and use that instead */
		jedbin_output(&jed, tempjed, length);
		data = tempjed;
	}

	/* compute the hash of the data */
	hash_data_clear(hash);
	hash_compute(hash, data, length, HASH_SHA1 | HASH_CRC);

	/* output the name */
	status->total++;
	basename = core_filename_extract_base(astring_alloc(), name, FALSE);
	mame_printf_info("%-20s", astring_c(basename));
	astring_free(basename);

	/* see if we can find a match in the ROMs */
	match_roms(hash, length, &found);

	/* if we didn't find it, try to guess what it might be */
	if (found == 0)
	{
		/* if not a power of 2, assume it is a non-ROM file */
		if ((length & (length - 1)) != 0)
		{
			mame_printf_info("NOT A ROM\n");
			status->nonroms++;
		}

		/* otherwise, it's just not a match */
		else
			mame_printf_info("NO MATCH\n");
	}

	/* if we did find it, count it as a match */
	else
		status->matches++;

	/* free any temporary JED data */
	if (tempjed != NULL)
		free(tempjed);
}
Exemple #2
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;
}
/* Fills in an audit record for each rom in the romset. Sets 'audit' to
   point to the list of audit records. Returns total number of roms
   in the romset (same as number of audit records), 0 if romset missing. */
int audit_roms (int game, audit_record **audit)
{
	const rom_entry *region, *rom, *chunk;
	const char *name;
	const game_driver *gamedrv;
	const game_driver *clone_of;

	int count = 0;
	audit_record *aud;
	int	err;

	if (!audit_records)
	{
		audit_records = (audit_record *)malloc (AUD_MAX_ROMS * sizeof (audit_record));

		// Make sure the memory is cleared - it's needed by the hashing
		//  engine
		memset(audit_records, 0, AUD_MAX_ROMS * sizeof(audit_record));
	}

	if (audit_records)
		*audit = aud = audit_records;
	else
		return 0;

	gamedrv = drivers[game];
	clone_of = driver_get_clone(gamedrv);

	if (!gamedrv->rom) return -1;

	/* check for existence of romset */
	if (!mame_faccess (gamedrv->name, FILETYPE_ROM))
	{
		/* if the game is a clone, check for parent */
		if (clone_of == NULL || (clone_of->flags & NOT_A_DRIVER) ||
				!mame_faccess(clone_of->name,FILETYPE_ROM))
			return 0;
	}

	for (region = rom_first_region(gamedrv); region; region = rom_next_region(region))
		for (rom = rom_first_file(region); rom; rom = rom_next_file(rom))
		{
			if (ROMREGION_ISROMDATA(region))
			{
				const game_driver *drv;

				name = ROM_GETNAME(rom);
				strcpy (aud->rom, name);
				aud->explength = 0;
				aud->length = 0;
				aud->exphash = ROM_GETHASHDATA(rom);

				/* Copy into the variable we pass to the functions
                   to support load-by-checksum */
				hash_data_copy(aud->hash, aud->exphash);

				count++;

				/* obtain hash checksums and length of ROM file */
				drv = gamedrv;
				do
				{
					err = mame_fchecksum(drv->name, name, &aud->length, aud->hash);
					drv = driver_get_clone(drv);
				} while (err && drv);

				/* spin through ROM_CONTINUEs, totaling length */
				for (chunk = rom_first_chunk(rom); chunk; chunk = rom_next_chunk(chunk))
					aud->explength += ROM_GETLENGTH(chunk);

				if (err)
				{
					if (hash_data_has_info(aud->exphash, HASH_INFO_NO_DUMP))
					{
						/* not found but it's not good anyway */
						aud->status = AUD_NOT_AVAILABLE;
					}
					else if (ROM_ISOPTIONAL(rom))
					{
						/* optional ROM not found */
						aud->status = AUD_OPTIONAL_ROM_NOT_FOUND;
					}
					else
					{
						/* not found */
						aud->status = AUD_ROM_NOT_FOUND;

						drv = clone_of;

						/* If missing ROM is also present in a parent set, indicate that */
						while (drv)
						{
							if (audit_is_rom_used (drv, aud->exphash))
							{
								if (drv->flags & NOT_A_DRIVER)
								{
									aud->status = AUD_ROM_NOT_FOUND_BIOS;
									break;
								}
								else
									aud->status = AUD_ROM_NOT_FOUND_PARENT;
							}

							// Walk up the inheritance list. If this ROM is a clone of a set which
							// contains a BIOS that is missing, we can correctly mark it as
							// such.
							drv = driver_get_clone(drv);
						}
					}
				}
				/* all cases below assume the ROM was at least found */
				else if (aud->explength != aud->length)
					aud->status = AUD_LENGTH_MISMATCH;
				else if (hash_data_has_info(aud->exphash, HASH_INFO_NO_DUMP))
						aud->status = AUD_ROM_NEED_DUMP; /* new case - found but not known to be dumped */
				else if (!hash_data_is_equal(aud->exphash, aud->hash, 0))
				{
					/* non-matching hash */
						aud->status = AUD_BAD_CHECKSUM;
				}
				else
				{
					/* matching hash */
					if (hash_data_has_info(aud->exphash, HASH_INFO_BAD_DUMP))
						aud->status = AUD_ROM_NEED_REDUMP;
					else
					aud->status = AUD_ROM_GOOD;
				}

				aud++;
			}
			else if (ROMREGION_ISDISKDATA(region))
			{
				const UINT8 nullhash[HASH_BUF_SIZE] = { 0 };
				void *source;
				chd_header header;

				name = ROM_GETNAME(rom);
				strcpy (aud->rom, name);
				aud->explength = 0;
				aud->length = 0;
				aud->exphash = ROM_GETHASHDATA(rom);
				hash_data_clear(aud->hash);
				count++;

				chd_gamedrv = gamedrv;
				chd_set_interface(&audit_chd_interface);
				source = chd_open( name, 0, NULL );
				if( source == NULL )
				{
					err = chd_get_last_error();
					if( err == CHDERR_OUT_OF_MEMORY )
					{
						aud->status = AUD_MEM_ERROR;
					}
					else if (hash_data_has_info(aud->exphash, HASH_INFO_NO_DUMP))
					{
						/* not found but it's not good anyway */
						aud->status = AUD_DISK_NOT_AVAILABLE;
					}
					else
					{
						/* not found */
						aud->status = AUD_DISK_NOT_FOUND;
					}
				}
				else
				{
					header = *chd_get_header(source);

					if (memcmp(nullhash, header.md5, sizeof(header.md5)))
						hash_data_insert_binary_checksum(aud->hash, HASH_MD5, header.md5);
					if (memcmp(nullhash, header.sha1, sizeof(header.sha1)))
						hash_data_insert_binary_checksum(aud->hash, HASH_SHA1, header.sha1);

					 if (hash_data_has_info(aud->exphash, HASH_INFO_NO_DUMP))
					{
						aud->status = AUD_DISK_NEED_DUMP;
					}
					else if (!hash_data_is_equal(aud->exphash, aud->hash, 0))
					{
						aud->status = AUD_DISK_BAD_MD5;
					}
					else
					{
						aud->status = AUD_DISK_GOOD;
					}

					chd_close( source );
				}

				aud++;
			}
		}

        #ifdef MESS
        if (!count)
                return -1;
        else
        #endif
	return count;
}
Exemple #4
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++;
		}
	}
}
Exemple #5
0
static mame_file *generic_fopen(int pathtype, const char *gamename, const char *filename, const char* hash, UINT32 flags)
{
	static const char *access_modes[] = { "rb", "rb", "wb", "r+b" };
	const char *extension = get_extension_for_filetype(pathtype);
	int pathcount = osd_get_path_count(pathtype);
	int pathindex, pathstart, pathstop, pathinc;
	mame_file file, *newfile;
	char tempname[256];

	LOG(("generic_fopen(%d, %s, %s, %s, %X)\n", pathc, gamename, filename, extension, flags));

	/* reset the file handle */
	memset(&file, 0, sizeof(file));

	/* check for incompatible flags */
	if ((flags & FILEFLAG_OPENWRITE) && (flags & FILEFLAG_HASH))
		fprintf(stderr, "Can't use HASH option with WRITE option in generic_fopen!\n");

	/* determine start/stop based on reverse search flag */
	if (!(flags & FILEFLAG_REVERSE_SEARCH))
	{
		pathstart = 0;
		pathstop = pathcount;
		pathinc = 1;
	}
	else
	{
		pathstart = pathcount - 1;
		pathstop = -1;
		pathinc = -1;
	}

	/* loop over paths */
	for (pathindex = pathstart; pathindex != pathstop; pathindex += pathinc)
	{
		char name[1024];

		/* ----------------- STEP 1: OPEN THE FILE RAW -------------------- */

		/* first look for path/gamename as a directory */
		compose_path(name, gamename, NULL, NULL);
		LOG(("Trying %s\n", name));

		/* if the directory exists, proceed */
		if (*name == 0 || osd_get_path_info(pathtype, pathindex, name) == PATH_IS_DIRECTORY)
		{
			/* now look for path/gamename/filename.ext */
			compose_path(name, gamename, filename, extension);

			/* if we need checksums, load it into RAM and compute it along the way */
			if (flags & FILEFLAG_HASH)
			{
				if (checksum_file(pathtype, pathindex, name, &file.data, &file.length, file.hash) == 0)
				{
					file.type = RAM_FILE;
					break;
				}
			}

			/* otherwise, just open it straight */
			else
			{
				file.type = PLAIN_FILE;
				file.file = osd_fopen(pathtype, pathindex, name, access_modes[flags & 3]);
				if (file.file == NULL && (flags & 3) == 3)
					file.file = osd_fopen(pathtype, pathindex, name, "w+b");
				if (file.file != NULL)
					break;
			}
		}

		/* ----------------- STEP 2: OPEN THE FILE IN A ZIP -------------------- */

		/* now look for it within a ZIP file */
		if (!(flags & (FILEFLAG_OPENWRITE | FILEFLAG_NOZIP)))
		{
			/* first look for path/gamename.zip */
			compose_path(name, gamename, NULL, "zip");
			LOG(("Trying %s file\n", name));

			/* if the ZIP file exists, proceed */
			if (osd_get_path_info(pathtype, pathindex, name) == PATH_IS_FILE)
			{
				UINT32 ziplength;

				/* if the file was able to be extracted from the ZIP, continue */
				compose_path(tempname, NULL, filename, extension);

				/* verify-only case */
				if (flags & FILEFLAG_VERIFY_ONLY)
				{
					UINT8 crcs[4];
					UINT32 crc = 0;

					/* Since this is a .ZIP file, we extract the CRC from the expected hash
					   (if any), so that we can load by CRC if needed. We must check that
					   the hash really contains a CRC, because it could be a NO_DUMP rom
					   for which we do not know the CRC yet. */
					if (hash && hash_data_extract_binary_checksum(hash, HASH_CRC, crcs) != 0)
					{
						/* Store the CRC in a single DWORD */
						crc = ((unsigned long)crcs[0] << 24) |
							  ((unsigned long)crcs[1] << 16) |
							  ((unsigned long)crcs[2] <<  8) |
							  ((unsigned long)crcs[3] <<  0);
					}

					hash_data_clear(file.hash);
						
					if (checksum_zipped_file(pathtype, pathindex, name, tempname, &ziplength, &crc) == 0)
					{
						file.length = ziplength;
						file.type = UNLOADED_ZIPPED_FILE;
						crcs[0] = (UINT8)(crc >> 24);
						crcs[1] = (UINT8)(crc >> 16);
						crcs[2] = (UINT8)(crc >> 8);
						crcs[3] = (UINT8)(crc >> 0);
						hash_data_insert_binary_checksum(file.hash, HASH_CRC, crcs);
						break;
					}
				}
Exemple #6
0
static void identify_file(core_options *options, const char *name, romident_status *status)
{
	file_error filerr;
	osd_file *file;
	UINT64 length;

	if (core_filename_ends_with(name, ".chd"))
	{
		chd_file *chd;
		chd_error err;
		astring basename;
		int found = 0;

		core_filename_extract_base(&basename, name, FALSE);
		mame_printf_info("%-20s", basename.cstr());

		status->total++;

		err = chd_open(name, CHD_OPEN_READ, NULL, &chd);
		if (err != CHDERR_NONE)
		{
			mame_printf_info("NOT A CHD\n");
			status->nonroms++;
		}
		else
		{
			chd_header header;

			header = *chd_get_header(chd);
			if (header.flags & CHDFLAGS_IS_WRITEABLE)
			{
				mame_printf_info("is a writable CHD\n");
			}
			else
			{
				static const UINT8 nullhash[HASH_BUF_SIZE] = { 0 };
				char			hash[HASH_BUF_SIZE];	/* actual hash information */

				hash_data_clear(hash);

				/* if there's an MD5 or SHA1 hash, add them to the output hash */
				if (memcmp(nullhash, header.md5, sizeof(header.md5)) != 0)
					hash_data_insert_binary_checksum(hash, HASH_MD5, header.md5);
				if (memcmp(nullhash, header.sha1, sizeof(header.sha1)) != 0)
					hash_data_insert_binary_checksum(hash, HASH_SHA1, header.sha1);

				length = header.logicalbytes;

				match_roms(options, hash, length, &found);

				if (found == 0)
				{
					mame_printf_info("NO MATCH\n");
				}

				/* if we did find it, count it as a match */
				else
					status->matches++;
			}

			chd_close(chd);
		}
	}
	else
	{
		/* open for read and process if it opens and has a valid length */
		filerr = osd_open(name, OPEN_FLAG_READ, &file, &length);
		if (filerr == FILERR_NONE && length > 0 && (UINT32)length == length)
		{
			UINT8 *data = global_alloc_array(UINT8, length);
			if (data != NULL)
			{
				UINT32 bytes;

				/* read file data into RAM and identify it */
				filerr = osd_read(file, data, 0, length, &bytes);
				if (filerr == FILERR_NONE)
					identify_data(options, name, data, bytes, status);
				global_free(data);
			}
			osd_close(file);
		}
	}
}