⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 williams.c

📁 这个是延伸mame的在wince平台下的游戏模拟器的代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************

  vidhrdw.c

  Functions to emulate the video hardware of the machine.

***************************************************************************/

#include "driver.h"
#include "vidhrdw/generic.h"


extern unsigned char *williams_bank_select;
extern unsigned char *blaster_bank_ram;

extern int sinistar_clip;
extern int williams_cocktail;

extern void williams_vram_select_w (int offset, int data);


unsigned char *williams_blitterram;
unsigned char *williams_videoram;
unsigned char *williams_remap_select;

unsigned char *blaster_video_bits;
unsigned char *blaster_color_zero_table;
unsigned char *blaster_color_zero_flags;


static const unsigned char *williams_remap;
static unsigned char *williams_remap_lookup;
static struct osd_bitmap *williams_bitmap;

static int blitter_xor;
static int blitter_solid;

static int blaster_erase_screen;


/* pixel plotters */

typedef void (*put_pix_func) (int offset, int pix);

static put_pix_func put_pix;

static void put_pix_normal (int offset, int pix);
static void put_pix_fx (int offset, int pix);
static void put_pix_fy (int offset, int pix);
static void put_pix_fx_fy (int offset, int pix);

static void put_pix_swap (int offset, int pix);
static void put_pix_swap_fx (int offset, int pix);
static void put_pix_swap_fy (int offset, int pix);
static void put_pix_swap_fx_fy (int offset, int pix);


/* blitter functions */

typedef void (*blitter_func)(int, int, int);

static blitter_func transparent_blitter_w;
static blitter_func transparent_solid_blitter_w;
static blitter_func opaque_blitter_w;
static blitter_func opaque_solid_blitter_w;

static void williams_transparent_blitter_w (int offset, int data, int keepmask);
static void williams_transparent_solid_blitter_w (int offset, int data, int keepmask);
static void williams_opaque_blitter_w (int offset, int data, int keepmask);
static void williams_opaque_solid_blitter_w (int offset, int data, int keepmask);

static void remap_transparent_blitter_w (int offset, int data, int keepmask);
static void remap_transparent_solid_blitter_w (int offset, int data, int keepmask);
static void remap_opaque_blitter_w (int offset, int data, int keepmask);

static void sinistar_transparent_blitter_w (int offset, int data, int keepmask);
static void sinistar_transparent_solid_blitter_w (int offset, int data, int keepmask);
static void sinistar_opaque_blitter_w (int offset, int data, int keepmask);
static void sinistar_opaque_solid_blitter_w (int offset, int data, int keepmask);



/***************************************************************************

	Common Williams routines

***************************************************************************/

void williams_vh_convert_color_prom (unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom)
{
	/* no remap table by default */
	williams_remap_lookup = 0;
}


/*
 *  Start the video hardware emulation
 */

int williams_vh_start (void)
{
	/* Allocate the offscreen bitmap */
	williams_bitmap = osd_create_bitmap (Machine->drv->screen_width, Machine->drv->screen_height);
	if (!williams_bitmap)
		return 1;

	/* Allocate space for video ram  */
	if ((williams_videoram = malloc (videoram_size)) == 0)
	{
		osd_free_bitmap (williams_bitmap);
		return 1;
	}
	memset (williams_videoram, 0, videoram_size);

	/* By default xor with 4 (SC1 chip) */
	blitter_xor = 4;

	/* Set up the standard blitters */
	transparent_blitter_w = williams_remap_lookup ? remap_transparent_blitter_w : williams_transparent_blitter_w;
	opaque_blitter_w = williams_remap_lookup ? remap_opaque_blitter_w : williams_opaque_blitter_w;
	transparent_solid_blitter_w = williams_remap_lookup ? remap_transparent_solid_blitter_w : williams_transparent_solid_blitter_w;
	opaque_solid_blitter_w = williams_opaque_solid_blitter_w;

	/* Reset the erase screen flag */
	blaster_erase_screen = 0;

	/* Set up the pixel plotter */
	if (Machine->orientation & ORIENTATION_SWAP_XY)
	{
		if (Machine->orientation & ORIENTATION_FLIP_Y)
		{
			if (Machine->orientation & ORIENTATION_FLIP_X)
				put_pix = put_pix_swap_fx_fy;
			else
				put_pix = put_pix_swap_fy;
		}
		else
		{
			if (Machine->orientation & ORIENTATION_FLIP_X)
				put_pix = put_pix_swap_fx;
			else
				put_pix = put_pix_swap;
		}
	}
	else
	{
		if (Machine->orientation & ORIENTATION_FLIP_Y)
		{
			if (Machine->orientation & ORIENTATION_FLIP_X)
				put_pix = put_pix_fx_fy;
			else
				put_pix = put_pix_fy;
		}
		else
		{
			if (Machine->orientation & ORIENTATION_FLIP_X)
				put_pix = put_pix_fx;
			else
				put_pix = put_pix_normal;
		}
	}

	return 0;
}


/*
 *  Start the video hardware emulation, but for an SC2 chip game
 */

int williams_vh_start_sc2 (void)
{
	int result = williams_vh_start ();

	/* the SC2 chip fixes the xor bug */
	blitter_xor = 0;

	return result;
}


/*
 *  Stop the video hardware emulation
 */

void williams_vh_stop (void)
{
	/* free any remap lookup tables */
	if (williams_remap_lookup)
		free (williams_remap_lookup);
	williams_remap_lookup = 0;

	/* free other stuff */
	free (williams_videoram);
	osd_free_bitmap (williams_bitmap);
}


/*
 *  Update part of the screen (note that we go directly to the scrbitmap here!)
 */

void williams_vh_update (int counter)
{
	struct rectangle clip;

	/* we only update every 16 scan lines to keep things moving reasonably */
	if (counter & 0x0f) return;

	/* wrap around at the bottom */
	if (counter == 0) counter = 256;

	/* determine the clip rect */
	clip.min_x = 0;
	clip.max_x = Machine->drv->screen_width - 1;
	clip.min_y = counter - 16;
	clip.max_y = clip.min_y + 15;

	/* combine the clip rect with the visible rect */
	if (Machine->drv->visible_area.min_x > clip.min_x)
		clip.min_x = Machine->drv->visible_area.min_x;
	if (Machine->drv->visible_area.max_x < clip.max_x)
		clip.max_x = Machine->drv->visible_area.max_x;
	if (Machine->drv->visible_area.min_y > clip.min_y)
		clip.min_y = Machine->drv->visible_area.min_y;
	if (Machine->drv->visible_area.max_y < clip.max_y)
		clip.max_y = Machine->drv->visible_area.max_y;

	/* copy */
	copybitmap (Machine->scrbitmap, williams_bitmap, 0, 0, 0, 0, &clip, TRANSPARENCY_NONE, 0);

	/* optionally erase from lines 24 downward */
	if (blaster_erase_screen && clip.max_y > 24)
	{
		int offset, count;

		/* erase the actual bitmap */
		if (clip.min_y < 24) clip.min_y = 24;
		fillbitmap (williams_bitmap, Machine->pens[0], &clip);

		/* erase the memory associated with this area */
		count = clip.max_y - clip.min_y + 1;
		for (offset = clip.min_y; offset < videoram_size; offset += 0x100)
			memset (&williams_videoram[offset], 0, count);
	}
}


/*
 *  Video update - not needed, the video is updated in chunks
 */

void williams_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
{
}


/*
 *  Generic videoram write function; works for every game
 */

void williams_videoram_w (int offset, int data)
{
	/* Put the byte in the videoram */
	williams_videoram[offset] = data;

	/* Put the pixels in our bitmap */
	(*put_pix) (offset, data);
}



/*
 *	Remap table select
 */

void williams_remap_select_w (int offset, int data)
{
	*williams_remap_select = data;
	williams_remap = williams_remap_lookup + data * 256;
}



/***************************************************************************

	Common blitter routines

***************************************************************************/

/*

	Blitter description from Sean Riddle's page:

	This page contains information about the Williams Special Chips, which
	were 'bit blitters'- block transfer chips that could move data around on
	the screen and in memory faster than the CPU. In fact, I've timed the
	special chips at 16 megs in 18.1 seconds. That's 910K/sec, not bad for
	the early 80s.

	The blitters were not used in Defender and Stargate, but
	were added to the ROM boards of the later games. Splat!, Blaster, Mystic
	Marathon and Joust 2 used Special Chip 2s. The only difference that I've
	seen is that SC1s have a small bug. When you tell the SC1 the size of
	the data to move, you have to exclusive-or the width and height with 2.
	The SC2s eliminate this bug.

	The blitters were accessed at memory location $CA00-CA06.

	CA01 is the mask, usually $FF to move all bits.
	CA02-3 is the source data location.
	CA04-5 is the destination data location.

	Writing to CA00 starts the blit, and the byte written determines how the
	data is blitted.

	Bit 0 indicates that the source data is either laid out linear, one
	pixel after the last, or in screen format, where there are 256 bytes from
	one pair of pixels to the next.

	Bit 1 indicates the same, but for the destination data.

	I'm not sure what bit 2 does. Looking at the image, I can't tell, but
	perhaps it has to do with the mask. My test files only used a mask of $FF.

	Bit 3 tells the blitter only to blit the foreground- that is, everything
	that is not color 0. Also known as transparency mode.

	Bit 4 is 'solid' mode. Only the color indicated by the mask is blitted.
	Note that this just creates a rectangle unless bit 3 is also set, in which
	case it blits the image, but in a solid color.

	Bit 5 shifts the image one pixel to the right. Any data on the far right
	jumps to the far left.

	Bits 6 and 7 only blit every other pixel of the image. Bit 6 says even only,
	while bit 7 says odd only.

*/


/*
 *  Macros for blitter destination read/write access
 */

#define williams_blitter_dest_r(o) (((o) < videoram_size) ? williams_videoram[o] : cpu_readmem16 (o))
#define williams_blitter_dest_w(o,v) if ((o) < videoram_size) { williams_videoram[o] = (v); (*put_pix)((o), (v)); } else cpu_writemem16 ((o), (v))


/*
 *  Handler for the actual writes to the blitter
 */

void williams_blitter_w (int offset, int data)
{
	blitter_func blitter_w;
	int source, sstart, sxadv, syadv;
	int dest, dstart, dxadv, dyadv;
	int i, j, w, h;
	int keepmask;

	/* only writes to location 0 trigger the blit */
	if (offset)
	{
		williams_blitterram[offset] = data;
		return;
	}

	/* compute the starting locations */
	sstart = (williams_blitterram[2] << 8) + williams_blitterram[3];
	dstart = (williams_blitterram[4] << 8) + williams_blitterram[5];

	/* compute the width and height */
	w = williams_blitterram[6] ^ blitter_xor;
	h = williams_blitterram[7] ^ blitter_xor;

	/* adjust the width and height */
	if (w == 0) w = 1;
	if (h == 0) h = 1;
	if (w == 255) w = 256;
	if (h == 255) h = 256;

	/* compute how much to advance in the x and y loops */
	sxadv = (data & 0x01) ? 0x100 : 1;
	syadv = (data & 0x01) ? 1 : w;
	dxadv = (data & 0x02) ? 0x100 : 1;
	dyadv = (data & 0x02) ? 1 : w;

	/* determine the common mask */
	keepmask = 0x00;
	if (data & 0x80) keepmask |= 0xf0;
	if (data & 0x40) keepmask |= 0x0f;
	if (keepmask == 0xff)
		return;

	/* set the solid pixel value to the mask value */
	blitter_solid = williams_blitterram[1];

	/* pick the blitter */
	if (data & 0x10)
		blitter_w = (data & 0x08) ? transparent_solid_blitter_w : opaque_solid_blitter_w;
	else
		blitter_w = (data & 0x08) ? transparent_blitter_w : opaque_blitter_w;

	/* first case: no shifting */
	if (!(data & 0x20))
	{
		/* loop over the height */
		for (i = 0; i < h; i++)
		{
			source = sstart & 0xffff;
			dest = dstart & 0xffff;

			/* loop over the width */
			for (j = w; j > 0; j--)
			{
				(*blitter_w) (dest, cpu_readmem16 (source), keepmask);

				source = (source + sxadv) & 0xffff;
				dest   = (dest + dxadv) & 0xffff;
			}

			sstart += syadv;
			dstart += dyadv;
		}
	}

	/* second case: shifted one pixel */
	else
	{

⌨️ 快捷键说明

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