欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

romcmp.c

显示compatiblemodes的算法
C
第 1 页 / 共 2 页
字号:
		{
			/* normal compare */
			for (i = 0;i < size1;i++)
				if (file1->buf[base1 + mult1 * i] == file2->buf[base2 + mult2 * i]) match++;
		}
		else
		{
			/* nibble compare, abort if other half is not empty */
			for (i = 0;i < size1;i++)
			{
				if (((file1->buf[base1 + mult1 * i] & ~mask1) != (0x00 & ~mask1) &&
					 (file1->buf[base1 + mult1 * i] & ~mask1) != (0xff & ~mask1)) ||
					((file2->buf[base1 + mult1 * i] & ~mask2) != (0x00 & ~mask2) &&
					 (file2->buf[base1 + mult1 * i] & ~mask2) != (0xff & ~mask2)))
				{
					match = 0;
					break;
				}
				if ((file1->buf[base1 + mult1 * i] & mask1) == (file2->buf[base2 + mult2 * i] & mask2)) match++;
			}
		}
	}

	return (float)match / size1;
}


static void readfile(const char *path,fileinfo *file)
{
	file_error filerr;
	UINT64 filesize;
	UINT32 actual;
	char fullname[256];
	osd_file *f = 0;

	if (path)
	{
		char delim[2] = { PATH_DELIM, '\0' };
		strcpy(fullname,path);
		strcat(fullname,delim);
	}
	else fullname[0] = 0;
	strcat(fullname,file->name);

	if ((file->buf = malloc(file->size)) == 0)
	{
		printf("%s: out of memory!\n",file->name);
		return;
	}

	filerr = osd_open(fullname, OPEN_FLAG_READ, &f, &filesize);
	if (filerr != FILERR_NONE)
	{
		printf("%s: error %d\n", fullname, filerr);
		return;
	}

	filerr = osd_read(f, file->buf, 0, file->size, &actual);
	if (filerr != FILERR_NONE)
	{
		printf("%s: error %d\n", fullname, filerr);
		osd_close(f);
		return;
	}

	osd_close(f);
}


static void freefile(fileinfo *file)
{
	free(file->buf);
	file->buf = 0;
}


static void printname(const fileinfo *file1,const fileinfo *file2,float score,int mode1,int mode2)
{
	printf("%-12s %s %-12s %s ",file1 ? file1->name : "",modenames[mode1],file2 ? file2->name : "",modenames[mode2]);
	if (score == 0.0) printf("NO MATCH\n");
	else if (score == 1.0) printf("IDENTICAL\n");
	else printf("%3.6f%%\n",score*100);
}


static int load_files(int i, int *found, const char *path)
{
	osd_directory *dir;

	/* attempt to open as a directory first */
	dir = osd_opendir(path);
	if (dir != NULL)
	{
		const osd_directory_entry *d;

		/* load all files in directory */
		while ((d = osd_readdir(dir)) != NULL)
		{
			const char *d_name = d->name;
			char buf[255+1];

			sprintf(buf, "%s%c%s", path, PATH_DELIM, d_name);
			if (d->type == ENTTYPE_FILE)
			{
				UINT64 size = d->size;
				while (size && (size & 1) == 0) size >>= 1;
				if (size & ~1)
					printf("%-23s %-23s ignored (not a ROM)\n",i ? "" : d_name,i ? d_name : "");
				else
				{
					strcpy(files[i][found[i]].name,d_name);
					files[i][found[i]].size = d->size;
					readfile(path,&files[i][found[i]]);
					files[i][found[i]].listed = 0;
					if (found[i] >= MAX_FILES)
					{
						printf("%s: max of %d files exceeded\n",path,MAX_FILES);
						break;
					}
					found[i]++;
				}
			}
		}
		osd_closedir(dir);
	}

	/* if not, try to open as a ZIP file */
	else
	{
		zip_file *zip;
		const zip_file_header* zipent;
		zip_error ziperr;

		/* wasn't a directory, so try to open it as a zip file */
		ziperr = zip_file_open(path, &zip);
		if (ziperr != ZIPERR_NONE)
		{
			printf("Error, cannot open zip file '%s' !\n", path);
			return 1;
		}

		/* load all files in zip file */
		for (zipent = zip_file_first_file(zip); zipent != NULL; zipent = zip_file_next_file(zip))
		{
			int size;

			size = zipent->uncompressed_length;
			while (size && (size & 1) == 0) size >>= 1;
			if (zipent->uncompressed_length == 0 || (size & ~1))
				printf("%-23s %-23s ignored (not a ROM)\n",
					i ? "" : zipent->filename, i ? zipent->filename : "");
			else
			{
				fileinfo *file = &files[i][found[i]];
				const char *delim = strrchr(zipent->filename,'/');

				if (delim)
					strcpy (file->name,delim+1);
				else
					strcpy(file->name,zipent->filename);
				file->size = zipent->uncompressed_length;
				if ((file->buf = malloc(file->size)) == 0)
					printf("%s: out of memory!\n",file->name);
				else
				{
					if (zip_file_decompress(zip, (char *)file->buf, file->size) != ZIPERR_NONE)
					{
						free(file->buf);
						file->buf = 0;
					}
				}

				file->listed = 0;
				if (found[i] >= MAX_FILES)
				{
					printf("%s: max of %d files exceeded\n",path,MAX_FILES);
					break;
				}
				found[i]++;
			}
		}
		zip_file_close(zip);
	}
	return 0;
}


#ifdef WIN32
int CLIB_DECL utf8_main(int argc,char **argv)
#else
int CLIB_DECL main(int argc,char **argv)
#endif
{
	int	err;
	int total_modes = MODE_NIB2;	/* by default, use only MODE_A, MODE_NIB1 and MODE_NIB2 */

	if (argc >= 2 && strcmp(argv[1],"-d") == 0)
	{
		argc--;
		argv++;
		total_modes = TOTAL_MODES;
	}

	if (argc < 2)
	{
		printf("usage: romcmp [-d] [dir1 | zip1] [dir2 | zip2]\n");
		printf("-d enables a slower, more comprehensive comparison.\n");
		return 0;
	}

	{
		int found[2];
		int i,j,mode1,mode2;
		int besti,bestj;


		found[0] = found[1] = 0;
		for (i = 0;i < 2;i++)
		{
			if (argc > i+1)
			{
				err = load_files (i, found, argv[i+1]);
				if (err != 0)
					return err;
			}
		}

		if (argc >= 3)
			printf("%d and %d files\n",found[0],found[1]);
		else
			printf("%d files\n",found[0]);

		for (i = 0;i < found[0];i++)
		{
			checkintegrity(&files[0][i],0);
		}

		for (j = 0;j < found[1];j++)
		{
			checkintegrity(&files[1][j],1);
		}

		if (argc < 3)
		{
			/* find duplicates in one dir */
			for (i = 0;i < found[0];i++)
			{
				for (j = i+1;j < found[0];j++)
				{
					for (mode1 = 0;mode1 < total_modes;mode1++)
					{
						for (mode2 = 0;mode2 < total_modes;mode2++)
						{
							if (filecompare(&files[0][i],&files[0][j],mode1,mode2) == 1.0)
								printname(&files[0][i],&files[0][j],1.0,mode1,mode2);
						}
					}
				}
			}
		}
		else
		{
			/* compare two dirs */
			for (i = 0;i < found[0];i++)
			{
				for (j = 0;j < found[1];j++)
				{
					fprintf(stderr,"%2d%%\r",100*(i*found[1]+j)/(found[0]*found[1]));
					for (mode1 = 0;mode1 < total_modes;mode1++)
					{
						for (mode2 = 0;mode2 < total_modes;mode2++)
						{
							matchscore[i][j][mode1][mode2] = filecompare(&files[0][i],&files[1][j],mode1,mode2);
						}
					}
				}
			}
			fprintf(stderr,"   \r");

			do
			{
				float bestscore;
				int bestmode1,bestmode2;

				besti = -1;
				bestj = -1;
				bestscore = 0.0;
				bestmode1 = bestmode2 = -1;

				for (mode1 = 0;mode1 < total_modes;mode1++)
				{
					for (mode2 = 0;mode2 < total_modes;mode2++)
					{
						for (i = 0;i < found[0];i++)
						{
							for (j = 0;j < found[1];j++)
							{
								if (matchscore[i][j][mode1][mode2] > bestscore
									|| (matchscore[i][j][mode1][mode2] == 1.0 && mode2 == 0 && bestmode2 > 0))
								{
									bestscore = matchscore[i][j][mode1][mode2];
									besti = i;
									bestj = j;
									bestmode1 = mode1;
									bestmode2 = mode2;
								}
							}
						}
					}
				}

				if (besti != -1)
				{
					int start,end;

					printname(&files[0][besti],&files[1][bestj],bestscore,bestmode1,bestmode2);
					files[0][besti].listed = 1;
					files[1][bestj].listed = 1;

					matchscore[besti][bestj][bestmode1][bestmode2] = 0.0;

					/* remove all matches using the same sections with a worse score */
					for (j = 0;j < found[1];j++)
					{
						for (mode2 = 0;mode2 < total_modes;mode2++)
						{
							if (matchscore[besti][j][bestmode1][mode2] < bestscore)
								matchscore[besti][j][bestmode1][mode2] = 0.0;
						}
					}
					for (i = 0;i < found[0];i++)
					{
						for (mode1 = 0;mode1 < total_modes;mode1++)
						{
							if (matchscore[i][bestj][mode1][bestmode2] < bestscore)
								matchscore[i][bestj][mode1][bestmode2] = 0.0;
						}
					}

					/* remove all matches using incompatible sections */
					compatiblemodes(bestmode1,&start,&end);
					for (j = 0;j < found[1];j++)
					{
						for (mode2 = 0;mode2 < total_modes;mode2++)
						{
							for (mode1 = 0;mode1 < start;mode1++)
								matchscore[besti][j][mode1][mode2] = 0.0;
							for (mode1 = end+1;mode1 < total_modes;mode1++)
								matchscore[besti][j][mode1][mode2] = 0.0;
						}
					}
					compatiblemodes(bestmode2,&start,&end);
					for (i = 0;i < found[0];i++)
					{
						for (mode1 = 0;mode1 < total_modes;mode1++)
						{
							for (mode2 = 0;mode2 < start;mode2++)
								matchscore[i][bestj][mode1][mode2] = 0.0;
							for (mode2 = end+1;mode2 < total_modes;mode2++)
								matchscore[i][bestj][mode1][mode2] = 0.0;
						}
					}
				}
			} while (besti != -1);


			for (i = 0;i < found[0];i++)
			{
				if (files[0][i].listed == 0) printname(&files[0][i],0,0.0,0,0);
				freefile(&files[0][i]);
			}
			for (i = 0;i < found[1];i++)
			{
				if (files[1][i].listed == 0) printname(0,&files[1][i],0.0,0,0);
				freefile(&files[1][i]);
			}
		}
	}

	zip_file_cache_clear();
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -