Exemple #1
0
BOOL LoadDIB(LPCTSTR filename, HGLOBAL *phDIB, HPALETTE *pPal, int pic_type)
{
	mame_file *mfile;
	BOOL success;
	const char *zip_name = NULL;

	switch (pic_type)
	{
	case TAB_SCREENSHOT :
		set_pathlist(FILETYPE_ARTWORK,GetImgDir());
		zip_name = "snap";
		break;
	case TAB_FLYER :
		set_pathlist(FILETYPE_ARTWORK,GetFlyerDir());
		zip_name = "flyers";
		break;
	case TAB_CABINET :
		set_pathlist(FILETYPE_ARTWORK,GetCabinetDir());
		zip_name = "cabinets";
		break;
	case TAB_MARQUEE :
		set_pathlist(FILETYPE_ARTWORK,GetMarqueeDir());
		zip_name = "marquees";
		break;
	case TAB_TITLE :
		set_pathlist(FILETYPE_ARTWORK,GetTitlesDir());
		zip_name = "titles";
		break;
	case TAB_CONTROL_PANEL :
		set_pathlist(FILETYPE_ARTWORK,GetControlPanelDir());
		zip_name = "cpanel";
		break;
	case BACKGROUND :
		set_pathlist(FILETYPE_ARTWORK,GetBgDir());
		zip_name = "bkground";
		break;
	default :
		// in case a non-image tab gets here, which can happen
		return FALSE;
	}
	
	// look for the raw file
	mfile = mame_fopen(NULL,filename,FILETYPE_ARTWORK,0);
	if (mfile == NULL)
	{
		// and look for the zip
		mfile = mame_fopen(zip_name,filename,FILETYPE_ARTWORK,0);
	}

	if (mfile == NULL)
		return FALSE;

	success = png_read_bitmap(mfile, phDIB, pPal);

	mame_fclose(mfile);

	return success;
}
Exemple #2
0
int main(int argc, char *argv[])
{
	// validate arguments
	if (argc < 3)
	{
		fprintf(stderr, "Usage:\n%s <input.png> [<input2.png> [...]] <output.bdc>\n", argv[0]);
		return 1;
	}
	const char *bdcname = argv[argc - 1];

	// iterate over input files
	static render_font font;
	bool error = false;
	// create font temporary file
	error = render_font_create_temporaryfile(font, bdcname);
	for (int curarg = 1; curarg < argc - 1; curarg++)
	{
		// load the png file
		const char *pngname = argv[curarg];
		core_file *file;
		file_error filerr = core_fopen(pngname, OPEN_FLAG_READ, &file);
		if (filerr != FILERR_NONE)
		{
			fprintf(stderr, "Error %d attempting to open PNG file\n", filerr);
			error = true;
			break;
		}

		bitmap_argb32 bitmap;
		png_error pngerr = png_read_bitmap(file, bitmap);
		core_fclose(file);
		if (pngerr != PNGERR_NONE)
		{
			fprintf(stderr, "Error %d reading PNG file\n", pngerr);
			error = true;
			break;
		}

		// parse the PNG into characters
		error = bitmap_to_chars(bitmap, font);
		if (error)
			break;

		// write out the resulting font
		error = render_font_save_cached(font, bdcname, 0);
		if (error)
			break;
	}

	// cleanup after ourselves
	return error ? 1 : 0;
}
Exemple #3
0
static int generate_png_diff(const summary_file *curfile, std::string &destdir, const char *destname)
{
	bitmap_argb32 bitmaps[MAX_COMPARES];
	std::string srcimgname;
	std::string dstfilename;
	std::string tempname;
	bitmap_argb32 finalbitmap;
	int width, height, maxwidth;
	int bitmapcount = 0;
	int listnum, bmnum;
	util::core_file::ptr file;
	osd_file::error filerr;
	png_error pngerr;
	int error = -1;
	int starty;

	/* generate the common source filename */
	dstfilename = string_format("%s" PATH_SEPARATOR "%s", destdir.c_str(), destname);
	srcimgname = string_format("snap" PATH_SEPARATOR "%s" PATH_SEPARATOR "final.png", curfile->name);

	/* open and load all unique bitmaps */
	for (listnum = 0; listnum < list_count; listnum++)
		if (curfile->matchbitmap[listnum] == listnum)
		{
			tempname = string_format("%s" PATH_SEPARATOR "%s", lists[listnum].dir, srcimgname.c_str());

			/* open the source image */
			filerr = util::core_file::open(tempname, OPEN_FLAG_READ, file);
			if (filerr != osd_file::error::NONE)
				goto error;

			/* load the source image */
			pngerr = png_read_bitmap(*file, bitmaps[bitmapcount++]);
			file.reset();
			if (pngerr != PNGERR_NONE)
				goto error;
		}

	/* if there's only one unique bitmap, skip it */
	if (bitmapcount <= 1)
		goto error;

	/* determine the size of the final bitmap */
	height = width = 0;
	maxwidth = bitmaps[0].width();
	for (bmnum = 1; bmnum < bitmapcount; bmnum++)
	{
		int curwidth;

		/* determine the maximal width */
		maxwidth = std::max(maxwidth, bitmaps[bmnum].width());
		curwidth = bitmaps[0].width() + BITMAP_SPACE + maxwidth + BITMAP_SPACE + maxwidth;
		width = std::max(width, curwidth);

		/* add to the height */
		height += std::max(bitmaps[0].height(), bitmaps[bmnum].height());
		if (bmnum != 1)
			height += BITMAP_SPACE;
	}

	/* allocate the final bitmap */
	finalbitmap.allocate(width, height);

	/* now copy and compare each set of bitmaps */
	starty = 0;
	for (bmnum = 1; bmnum < bitmapcount; bmnum++)
	{
		bitmap_argb32 &bitmap1 = bitmaps[0];
		bitmap_argb32 &bitmap2 = bitmaps[bmnum];
		int curheight = std::max(bitmap1.height(), bitmap2.height());
		int x, y;

		/* iterate over rows in these bitmaps */
		for (y = 0; y < curheight; y++)
		{
			UINT32 *src1 = (y < bitmap1.height()) ? &bitmap1.pix32(y) : nullptr;
			UINT32 *src2 = (y < bitmap2.height()) ? &bitmap2.pix32(y) : nullptr;
			UINT32 *dst1 = &finalbitmap.pix32(starty + y, 0);
			UINT32 *dst2 = &finalbitmap.pix32(starty + y, bitmap1.width() + BITMAP_SPACE);
			UINT32 *dstdiff = &finalbitmap.pix32(starty + y, bitmap1.width() + BITMAP_SPACE + maxwidth + BITMAP_SPACE);

			/* now iterate over columns */
			for (x = 0; x < maxwidth; x++)
			{
				int pix1 = -1, pix2 = -2;

				if (src1 != nullptr && x < bitmap1.width())
					pix1 = dst1[x] = src1[x];
				if (src2 != nullptr && x < bitmap2.width())
					pix2 = dst2[x] = src2[x];
				dstdiff[x] = (pix1 != pix2) ? 0xffffffff : 0xff000000;
			}
		}

		/* update the starting Y position */
		starty += BITMAP_SPACE + std::max(bitmap1.height(), bitmap2.height());
	}

	/* write the final PNG */
	filerr = util::core_file::open(dstfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
	if (filerr != osd_file::error::NONE)
		goto error;
	pngerr = png_write_bitmap(*file, nullptr, finalbitmap, 0, nullptr);
	file.reset();
	if (pngerr != PNGERR_NONE)
		goto error;

	/* if we get here, we are error free */
	error = 0;

error:
	if (error)
		osd_file::remove(dstfilename);
	return error;
}
Exemple #4
0
static int compare_screenshots(summary_file *curfile)
{
	bitmap_argb32 bitmaps[MAX_COMPARES];
	int unique[MAX_COMPARES];
	int numunique = 0;
	int listnum;

	/* iterate over all files and load their bitmaps */
	for (listnum = 0; listnum < list_count; listnum++)
		if (curfile->status[listnum] == STATUS_SUCCESS)
		{
			std::string fullname;
			osd_file::error filerr;
			util::core_file::ptr file;

			/* get the filename for the image */
			fullname = string_format("%s" PATH_SEPARATOR "snap" PATH_SEPARATOR "%s" PATH_SEPARATOR "final.png", lists[listnum].dir, curfile->name);

			/* open the file */
			filerr = util::core_file::open(fullname, OPEN_FLAG_READ, file);

			/* if that failed, look in the old location */
			if (filerr != osd_file::error::NONE)
			{
				/* get the filename for the image */
				fullname = string_format("%s" PATH_SEPARATOR "snap" PATH_SEPARATOR "_%s.png", lists[listnum].dir, curfile->name);

				/* open the file */
				filerr = util::core_file::open(fullname, OPEN_FLAG_READ, file);
			}

			/* if that worked, load the file */
			if (filerr == osd_file::error::NONE)
			{
				png_read_bitmap(*file, bitmaps[listnum]);
				file.reset();
			}
		}

	/* now find all the different bitmap types */
	for (listnum = 0; listnum < list_count; listnum++)
	{
		curfile->matchbitmap[listnum] = 0xff;
		if (bitmaps[listnum].valid())
		{
			bitmap_argb32 &this_bitmap = bitmaps[listnum];

			/* compare against all unique bitmaps */
			int compnum;
			for (compnum = 0; compnum < numunique; compnum++)
			{
				/* if the sizes are different, we differ; otherwise start off assuming we are the same */
				bitmap_argb32 &base_bitmap = bitmaps[unique[compnum]];
				bool bitmaps_differ = (this_bitmap.width() != base_bitmap.width() || this_bitmap.height() != base_bitmap.height());

				/* compare scanline by scanline */
				for (int y = 0; y < this_bitmap.height() && !bitmaps_differ; y++)
				{
					UINT32 *base = &base_bitmap.pix32(y);
					UINT32 *curr = &this_bitmap.pix32(y);

					/* scan the scanline */
					int x;
					for (x = 0; x < this_bitmap.width(); x++)
						if (*base++ != *curr++)
							break;
					bitmaps_differ = (x != this_bitmap.width());
				}

				/* if we matched, remember which listnum index we matched, and stop */
				if (!bitmaps_differ)
				{
					curfile->matchbitmap[listnum] = unique[compnum];
					break;
				}

				/* if different from the first unique entry, adjust the status */
				if (bitmaps_differ && compnum == 0)
					curfile->status[listnum] = STATUS_SUCCESS_DIFFERENT;
			}

			/* if we're unique, add ourselves to the list */
			if (compnum >= numunique)
			{
				unique[numunique++] = listnum;
				curfile->matchbitmap[listnum] = listnum;
				continue;
			}
		}
	}

	/* if all screenshots matched, we're good */
	if (numunique == 1)
		return BUCKET_GOOD;

	/* if the last screenshot matched the first unique one, we're good but changed */
	if (curfile->matchbitmap[listnum - 1] == unique[0])
		return BUCKET_GOOD_BUT_CHANGED_SCREENSHOTS;

	/* otherwise we're just changed */
	return BUCKET_CHANGED;
}
Exemple #5
0
BOOL LoadDIB(LPCTSTR filename, HGLOBAL *phDIB, HPALETTE *pPal, int pic_type)
{
	mame_file_error filerr;
	mame_file *mfile = NULL;
	char *fname;
	BOOL success;
	const char *zip_name = NULL;
	char *pngfilename = NULL;
	char tmp[MAX_PATH];
	strcpy(tmp, filename);
	strcat(tmp,  ".png");
	pngfilename = mame_strdup(tmp);
	switch (pic_type)
	{
	case TAB_SCREENSHOT :
		options_set_string(SEARCHPATH_ARTWORK,GetImgDir());
		zip_name = "snap";
		break;
	case TAB_FLYER :
		options_set_string(SEARCHPATH_ARTWORK,GetFlyerDir());
		zip_name = "flyers";
		break;
	case TAB_CABINET :
		options_set_string(SEARCHPATH_ARTWORK,GetCabinetDir());
		zip_name = "cabinets";
		break;
	case TAB_MARQUEE :
		options_set_string(SEARCHPATH_ARTWORK,GetMarqueeDir());
		zip_name = "marquees";
		break;
	case TAB_TITLE :
		options_set_string(SEARCHPATH_ARTWORK,GetTitlesDir());
		zip_name = "titles";
		break;
	case TAB_CONTROL_PANEL :
		options_set_string(SEARCHPATH_ARTWORK,GetControlPanelDir());
		zip_name = "cpanel";
		break;
	case BACKGROUND :
		options_set_string(SEARCHPATH_ARTWORK,GetBgDir());
		zip_name = "bkground";
		break;
	default :
		// in case a non-image tab gets here, which can happen
		return FALSE;
	}
	
	// look for the raw file
	filerr = mame_fopen(SEARCHPATH_ARTWORK, pngfilename, OPEN_FLAG_READ, &mfile);
	if (filerr != FILERR_NONE)
	{
		// and look for the zip
		fname = assemble_3_strings(zip_name, PATH_SEPARATOR, pngfilename);
		filerr = mame_fopen(SEARCHPATH_ARTWORK, fname, OPEN_FLAG_READ, &mfile);
		free(fname);
	}
	if (filerr != FILERR_NONE)
		return FALSE;

	success = png_read_bitmap(mfile, phDIB, pPal);

	mame_fclose(mfile);

	return success;
}
Exemple #6
0
static int generate_png_diff(const summary_file *curfile, const astring *destdir, const char *destname)
{
	bitmap_t *bitmaps[MAX_COMPARES] = { NULL };
	astring *srcimgname = astring_alloc();
	astring *dstfilename = astring_alloc();
	astring *tempname = astring_alloc();
	bitmap_t *finalbitmap = NULL;
	int width, height, maxwidth;
	int bitmapcount = 0;
	int listnum, bmnum;
	core_file *file = NULL;
	file_error filerr;
	png_error pngerr;
	int error = -1;
	int starty;

	/* generate the common source filename */
	astring_printf(dstfilename, "%s" PATH_SEPARATOR "%s", astring_c(destdir), destname);
	astring_printf(srcimgname, "snap" PATH_SEPARATOR "%s" PATH_SEPARATOR "final.png", curfile->name);

	/* open and load all unique bitmaps */
	for (listnum = 0; listnum < list_count; listnum++)
		if (curfile->matchbitmap[listnum] == listnum)
		{
			astring_printf(tempname, "%s" PATH_SEPARATOR "%s", lists[listnum].dir, astring_c(srcimgname));

			/* open the source image */
			filerr = core_fopen(astring_c(tempname), OPEN_FLAG_READ, &file);
			if (filerr != FILERR_NONE)
				goto error;

			/* load the source image */
			pngerr = png_read_bitmap(file, &bitmaps[bitmapcount++]);
			core_fclose(file);
			if (pngerr != PNGERR_NONE)
				goto error;
		}

	/* if there's only one unique bitmap, skip it */
	if (bitmapcount <= 1)
		goto error;

	/* determine the size of the final bitmap */
	height = width = 0;
	maxwidth = bitmaps[0]->width;
	for (bmnum = 1; bmnum < bitmapcount; bmnum++)
	{
		int curwidth;

		/* determine the maximal width */
		maxwidth = MAX(maxwidth, bitmaps[bmnum]->width);
		curwidth = bitmaps[0]->width + BITMAP_SPACE + maxwidth + BITMAP_SPACE + maxwidth;
		width = MAX(width, curwidth);

		/* add to the height */
		height += MAX(bitmaps[0]->height, bitmaps[bmnum]->height);
		if (bmnum != 1)
			height += BITMAP_SPACE;
	}

	/* allocate the final bitmap */
	finalbitmap = bitmap_alloc(width, height, BITMAP_FORMAT_ARGB32);
	if (finalbitmap == NULL)
		goto error;

	/* now copy and compare each set of bitmaps */
	starty = 0;
	for (bmnum = 1; bmnum < bitmapcount; bmnum++)
	{
		bitmap_t *bitmap1 = bitmaps[0];
		bitmap_t *bitmap2 = bitmaps[bmnum];
		int curheight = MAX(bitmap1->height, bitmap2->height);
		int x, y;

		/* iterate over rows in these bitmaps */
		for (y = 0; y < curheight; y++)
		{
			UINT32 *src1 = (y < bitmap1->height) ? BITMAP_ADDR32(bitmap1, y, 0) : NULL;
			UINT32 *src2 = (y < bitmap2->height) ? BITMAP_ADDR32(bitmap2, y, 0) : NULL;
			UINT32 *dst1 = BITMAP_ADDR32(finalbitmap, starty + y, 0);
			UINT32 *dst2 = BITMAP_ADDR32(finalbitmap, starty + y, bitmap1->width + BITMAP_SPACE);
			UINT32 *dstdiff = BITMAP_ADDR32(finalbitmap, starty + y, bitmap1->width + BITMAP_SPACE + maxwidth + BITMAP_SPACE);

			/* now iterate over columns */
			for (x = 0; x < maxwidth; x++)
			{
				int pix1 = -1, pix2 = -2;

				if (src1 != NULL && x < bitmap1->width)
					pix1 = dst1[x] = src1[x];
				if (src2 != NULL && x < bitmap2->width)
					pix2 = dst2[x] = src2[x];
				dstdiff[x] = (pix1 != pix2) ? 0xffffffff : 0xff000000;
			}
		}

		/* update the starting Y position */
		starty += BITMAP_SPACE + MAX(bitmap1->height, bitmap2->height);
	}

	/* write the final PNG */
	filerr = core_fopen(astring_c(dstfilename), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &file);
	if (filerr != FILERR_NONE)
		goto error;
	pngerr = png_write_bitmap(file, NULL, finalbitmap, 0, NULL);
	core_fclose(file);
	if (pngerr != PNGERR_NONE)
		goto error;

	/* if we get here, we are error free */
	error = 0;

error:
	if (finalbitmap != NULL)
		bitmap_free(finalbitmap);
	for (bmnum = 0; bmnum < bitmapcount; bmnum++)
		if (bitmaps[bmnum] != NULL)
			bitmap_free(bitmaps[bmnum]);
	if (error)
		osd_rmfile(astring_c(dstfilename));
	astring_free(dstfilename);
	astring_free(srcimgname);
	astring_free(tempname);
	return error;
}
Exemple #7
0
static int compare_screenshots(summary_file *curfile)
{
	bitmap_t *bitmaps[MAX_COMPARES];
	int unique[MAX_COMPARES];
	int numunique = 0;
	int listnum;

	/* iterate over all files and load their bitmaps */
	for (listnum = 0; listnum < list_count; listnum++)
	{
		bitmaps[listnum] = NULL;
		if (curfile->status[listnum] == STATUS_SUCCESS)
		{
			astring *fullname = astring_alloc();
			file_error filerr;
			core_file *file;

			/* get the filename for the image */
			astring_printf(fullname, "%s" PATH_SEPARATOR "snap" PATH_SEPARATOR "%s" PATH_SEPARATOR "final.png", lists[listnum].dir, curfile->name);

			/* open the file */
			filerr = core_fopen(astring_c(fullname), OPEN_FLAG_READ, &file);

			/* if that failed, look in the old location */
			if (filerr != FILERR_NONE)
			{
				/* get the filename for the image */
				astring_printf(fullname, "%s" PATH_SEPARATOR "snap" PATH_SEPARATOR "_%s.png", lists[listnum].dir, curfile->name);

				/* open the file */
				filerr = core_fopen(astring_c(fullname), OPEN_FLAG_READ, &file);
			}

			/* if that worked, load the file */
			if (filerr == FILERR_NONE)
			{
				png_read_bitmap(file, &bitmaps[listnum]);
				core_fclose(file);
			}
			astring_free(fullname);
		}
	}

	/* now find all the different bitmap types */
	for (listnum = 0; listnum < list_count; listnum++)
	{
		curfile->matchbitmap[listnum] = 0xff;
		if (bitmaps[listnum] != NULL)
		{
			bitmap_t *this_bitmap = bitmaps[listnum];
			int compnum;

			/* compare against all unique bitmaps */
			for (compnum = 0; compnum < numunique; compnum++)
			{
				bitmap_t *base_bitmap = bitmaps[unique[compnum]];
				int bitmaps_differ;
				int x, y;

				/* if the sizes are different, we differ; otherwise start off assuming we are the same */
				bitmaps_differ = (this_bitmap->width != base_bitmap->width || this_bitmap->height != base_bitmap->height);

				/* compare scanline by scanline */
				for (y = 0; y < this_bitmap->height && !bitmaps_differ; y++)
				{
					UINT32 *base = BITMAP_ADDR32(base_bitmap, y, 0);
					UINT32 *curr = BITMAP_ADDR32(this_bitmap, y, 0);

					/* scan the scanline */
					for (x = 0; x < this_bitmap->width; x++)
						if (*base++ != *curr++)
							break;
					bitmaps_differ = (x != this_bitmap->width);
				}

				/* if we matched, remember which listnum index we matched, and stop */
				if (!bitmaps_differ)
				{
					curfile->matchbitmap[listnum] = unique[compnum];
					break;
				}

				/* if different from the first unique entry, adjust the status */
				if (bitmaps_differ && compnum == 0)
					curfile->status[listnum] = STATUS_SUCCESS_DIFFERENT;
			}

			/* if we're unique, add ourselves to the list */
			if (compnum >= numunique)
			{
				unique[numunique++] = listnum;
				curfile->matchbitmap[listnum] = listnum;
				continue;
			}
		}
	}

	/* free the bitmaps */
	for (listnum = 0; listnum < list_count; listnum++)
		if (bitmaps[listnum] != NULL)
			bitmap_free(bitmaps[listnum]);

	/* if all screenshots matched, we're good */
	if (numunique == 1)
		return BUCKET_GOOD;

	/* if the last screenshot matched the first unique one, we're good but changed */
	if (curfile->matchbitmap[listnum - 1] == unique[0])
		return BUCKET_GOOD_BUT_CHANGED_SCREENSHOTS;

	/* otherwise we're just changed */
	return BUCKET_CHANGED;
}
Exemple #8
0
static int generate_png_diff(const astring& imgfile1, const astring& imgfile2, const astring& outfilename)
{
	bitmap_argb32 bitmap1;
	bitmap_argb32 bitmap2;
	bitmap_argb32 finalbitmap;
	int width, height, maxwidth;
	core_file *file = NULL;
	file_error filerr;
	png_error pngerr;
	int error = 100;
	bool bitmaps_differ;
	int x, y;

	/* open the source image */
	filerr = core_fopen(imgfile1, OPEN_FLAG_READ, &file);
	if (filerr != FILERR_NONE)
	{
		printf("Could not open %s (%d)\n", imgfile1.cstr(), filerr);
		goto error;
	}

	/* load the source image */
	pngerr = png_read_bitmap(file, bitmap1);
	core_fclose(file);
	if (pngerr != PNGERR_NONE)
	{
		printf("Could not read %s (%d)\n", imgfile1.cstr(), pngerr);
		goto error;
	}

	/* open the source image */
	filerr = core_fopen(imgfile2, OPEN_FLAG_READ, &file);
	if (filerr != FILERR_NONE)
	{
		printf("Could not open %s (%d)\n", imgfile2.cstr(), filerr);
		goto error;
	}

	/* load the source image */
	pngerr = png_read_bitmap(file, bitmap2);
	core_fclose(file);
	if (pngerr != PNGERR_NONE)
	{
		printf("Could not read %s (%d)\n", imgfile2.cstr(), pngerr);
		goto error;
	}

	/* if the sizes are different, we differ; otherwise start off assuming we are the same */
	bitmaps_differ = (bitmap2.width() != bitmap1.width() || bitmap2.height() != bitmap1.height());

	/* compare scanline by scanline */
	for (y = 0; y < bitmap2.height() && !bitmaps_differ; y++)
	{
		UINT32 *base = &bitmap1.pix32(y);
		UINT32 *curr = &bitmap2.pix32(y);

		/* scan the scanline */
		for (x = 0; x < bitmap2.width(); x++)
			if (*base++ != *curr++)
				break;
		bitmaps_differ = (x != bitmap2.width());
	}

	if (bitmaps_differ)
	{
		/* determine the size of the final bitmap */
		height = width = 0;
		{
			/* determine the maximal width */
			maxwidth = MAX(bitmap1.width(), bitmap2.width());
			width = bitmap1.width() + BITMAP_SPACE + maxwidth + BITMAP_SPACE + maxwidth;

			/* add to the height */
			height += MAX(bitmap1.height(), bitmap2.height());
		}

		/* allocate the final bitmap */
		finalbitmap.allocate(width, height);

		/* now copy and compare each set of bitmaps */
		int curheight = MAX(bitmap1.height(), bitmap2.height());
		/* iterate over rows in these bitmaps */
		for (y = 0; y < curheight; y++)
		{
			UINT32 *src1 = (y < bitmap1.height()) ? &bitmap1.pix32(y) : NULL;
			UINT32 *src2 = (y < bitmap2.height()) ? &bitmap2.pix32(y) : NULL;
			UINT32 *dst1 = &finalbitmap.pix32(y);
			UINT32 *dst2 = &finalbitmap.pix32(y, bitmap1.width() + BITMAP_SPACE);
			UINT32 *dstdiff = &finalbitmap.pix32(y, bitmap1.width() + BITMAP_SPACE + maxwidth + BITMAP_SPACE);

			/* now iterate over columns */
			for (x = 0; x < maxwidth; x++)
			{
				int pix1 = -1, pix2 = -2;

				if (src1 != NULL && x < bitmap1.width())
					pix1 = dst1[x] = src1[x];
				if (src2 != NULL && x < bitmap2.width())
					pix2 = dst2[x] = src2[x];
				dstdiff[x] = (pix1 != pix2) ? 0xffffffff : 0xff000000;
			}
		}

		/* write the final PNG */
		filerr = core_fopen(outfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &file);
		if (filerr != FILERR_NONE)
		{
			printf("Could not open %s (%d)\n", outfilename.cstr(), filerr);
			goto error;
		}
		pngerr = png_write_bitmap(file, NULL, finalbitmap, 0, NULL);
		core_fclose(file);
		if (pngerr != PNGERR_NONE)
		{
			printf("Could not write %s (%d)\n", outfilename.cstr(), pngerr);
			goto error;
		}
	}

	/* if we get here, we are error free */
	if (bitmaps_differ)
		error = 1;
	else
		error = 0;

error:
	if (error == -1)
		osd_rmfile(outfilename);
	return error;
}