vector.c

来自「这个是延伸mame的在wince平台下的游戏模拟器的代码」· C语言 代码 · 共 802 行 · 第 1/2 页

C
802
字号
/****************************************************************************** * * vector.c * * * Copyright 1997,1998 by the M.A.M.E. Project * *        anti-alias code by Andrew Caldwell *        (still more to add) * * 980611 use translucent vectors. Thanks to Peter Hirschberg *        and Neil Bradley for the inspiration. BW * 980307 added cleverer dirty handling. BW, ASG *        fixed antialias table .ac * 980221 rewrote anti-alias line draw routine *        added inline assembly multiply fuction for 8086 based machines *        beam diameter added to draw routine *        beam diameter is accurate in anti-alias line draw (Tcosin) *        flicker added .ac * 980203 moved LBO's routines for drawing into a buffer of vertices *        from avgdvg.c to this location. Scaling is now initialized *        by calling vector_init(...). BW * 980202 moved out of msdos.c ASG * 980124 added anti-alias line draw routine *        modified avgdvg.c and sega.c to support new line draw routine *        added two new tables Tinten and Tmerge (for 256 color support) *        added find_color routine to build above tables .ac * **************************************************************************** *//* GLmame and FXmame provide their own vector implementations */#if !(defined xgl) && !(defined xfx) && !(defined svgafx)#include <math.h>#include "osinline.h"#include "driver.h"#include "osdepend.h"#include "vector.h"#define VCLEAN  0#define VDIRTY  1#define VCLIP   2unsigned char *vectorram;int vectorram_size;int antialias;                            /* flag for anti-aliasing */int beam;                                 /* size of vector beam    */int flicker;                              /* beam flicker value     */int translucency;static int beam_diameter_is_one = 0;      /* flag that beam is one pixel wide */static int vector_scale_x;                /* scaling to screen */static int vector_scale_y;                /* scaling to screen *//* The vectices are buffered here */typedef struct{	int x; int y;	int col;	int intensity;	int arg1; int arg2; /* start/end in pixel array or clipping info */	int status;         /* for dirty and clipping handling */} point;static point *new_list;static point *old_list;static int new_index;static int old_index;/* coordinates of pixels are stored here for faster removal */static unsigned int *pixel;static int p_index=0;static unsigned int  *pTcosin;            /* adjust line width */static unsigned char *pTinten;            /* intensity         */static unsigned char *pTmerge;            /* mergeing pixels   */#define Tcosin(x)   pTcosin[(x)]          /* adjust line width */#define Tinten(x,y) pTinten[(x)*256+(y)]  /* intensity         */#define Tmerge(x,y) pTmerge[(x)*256+(y)]  /* mergeing pixels   */#define ANTIALIAS_GUNBIT  6             /* 6 bits per gun in vga (1-8 valid) */#define ANTIALIAS_GUNNUM  (1<<ANTIALIAS_GUNBIT)static unsigned char Tgamma[256];         /* quick gamma anti-alias table  */static unsigned char Tgammar[256];        /* same as above, reversed order */static struct osd_bitmap *vecbitmap;static int vecwidth, vecheight;static int vecshift;static int xmin, ymin, xmax, ymax; /* clipping area */static int vector_runs;	/* vector runs per refresh *//* * multiply and divide routines for drawing lines * can be be replaced by an assembly routine in osinline.h */#ifndef vec_multINLINE int vec_mult(int parm1, int parm2){	int temp,result;	temp     = abs(parm1);	result   = (temp&0x0000ffff) * (parm2&0x0000ffff);	result >>= 16;	result  += (temp&0x0000ffff) * (parm2>>16       );	result  += (temp>>16       ) * (parm2&0x0000ffff);	result >>= 16;	result  += (temp>>16       ) * (parm2>>16       );	if( parm1 < 0 )		return(-result);	else		return( result);}#endif/* can be be replaced by an assembly routine in osinline.h */#ifndef vec_divINLINE int vec_div(int parm1, int parm2){	if( (parm2>>12) )	{		parm1 = (parm1<<4) / (parm2>>12);		if( parm1 > 0x00010000 )			return( 0x00010000 );		if( parm1 < -0x00010000 )			return( -0x00010000 );		return( parm1 );	}	return( 0x00010000 );}#endif/* * finds closest color and returns the index (for 256 color) */static unsigned char find_color(unsigned char r,unsigned char g,unsigned char b){	int i,bi,ii;	long x,y,z,bc;	ii = 32;	bi = 256;	bc = 0x01000000;	do	{		for( i=0; i<256; i++ )		{			unsigned char r1,g1,b1;			osd_get_pen(i,&r1,&g1,&b1);			if((x=(long)(abs(r1-r)+1)) > ii) continue;			if((y=(long)(abs(g1-g)+1)) > ii) continue;			if((z=(long)(abs(b1-b)+1)) > ii) continue;			x = x*y*z;			if (x < bc)			{				bc = x;				bi = i;			}		}		ii<<=1;	} while (bi==256);	return(bi);}/* * Initializes vector game video emulation */int vector_vh_start (void){	int h,i,j,k,c[3];	if (beam == 0x00010000)		beam_diameter_is_one = 1;	p_index=0;	new_index = 0;	old_index = 0;	vector_runs = 0;	/* allocate memory for tables */	pTcosin = malloc ( (2048+1) * sizeof(int));   /* yes! 2049 is correct */	pTinten = malloc ( 256 * 256 * sizeof(unsigned char));	pTmerge = malloc (256 * 256 * sizeof(unsigned char));	pixel = malloc (MAX_PIXELS * sizeof (unsigned int));	old_list = malloc (MAX_POINTS * sizeof (point));	new_list = malloc (MAX_POINTS * sizeof (point));	/* did we get the requested memory? */	if (!(pTcosin && pTinten && pTmerge && pixel && old_list && new_list))	{		/* vector_vh_stop should better be called by the main engine */		/* if vector_vh_start fails */		vector_vh_stop();		return 1;	}	/* build cosine table for fixing line width in antialias */	for (i=0; i<=2048; i++)	{		Tcosin(i) = (int)((double)(1.0/cos(atan((double)(i)/2048.0)))*0x10000000 + 0.5);		/*printf ("cos %08x\n", Tcosin(i) );*/	}	/* build anti-alias table */	h = 256 / ANTIALIAS_GUNNUM;           /* to generate table faster */	for (i=0; i<256; i+=h )               /* intensity */	{		for (j=0; j<256; j++)               /* color */		{			unsigned char r1,g1,b1,col,n;			osd_get_pen(j,&r1,&g1,&b1);			col = find_color( (r1*(i+1))>>8, (g1*(i+1))>>8, (b1*(i+1))>>8 );			for (n=0; n<h; n++ )			{				Tinten(i+n,j) = col;			}		}	}	/* build merge color table */	for( i=0; i<256 ;i++ )                /* color1 */	{		unsigned char rgb1[3],rgb2[3];		osd_get_pen(i,&rgb1[0],&rgb1[1],&rgb1[2]);		for( j=0; j<=i ;j++ )               /* color2 */		{			osd_get_pen(j,&rgb2[0],&rgb2[1],&rgb2[2]);			for (k=0; k<3; k++)			if (translucency) /* add gun values */			{				int tmp;				tmp = rgb1[k] + rgb2[k];				if (tmp > 255)					c[k] = 255;				else					c[k] = tmp;			}			else /* choose highest gun value */			{				if (rgb1[k] > rgb2[k])					c[k] = rgb1[k];				else					c[k] = rgb2[k];			}			Tmerge(i,j) = Tmerge(j,i) = find_color(c[0],c[1],c[2]);		}	}	/* build gamma correction table */	for (i=0; i<256; i++)	{		h = i + (i>>2);		if( h > 255) h = 255;		Tgamma[i] = Tgammar[255-i] = h;	}	return 0;}/* * Setup scaling. Currently the Sega games are stuck at VECSHIFT 15 * and the the AVG games at VECSHIFT 16 */void vector_set_shift (int shift){	vecshift = shift;}/* * Clear the old bitmap. Delete pixel for pixel, this is faster than memset. */static void vector_clear_pixels (void){	unsigned char bg=Machine->pens[0];	int i;	int coords;	for (i=p_index-1; i>=0; i--)	{		coords = pixel[i];		vecbitmap->line[coords & 0x0000ffff][coords >> 16] = bg;	}	p_index=0;}/* * Stop the vector video hardware emulation. Free memory. */void vector_vh_stop (void){	if (pTcosin)		free (pTcosin);	pTcosin = NULL;	if (pTinten)		free (pTinten);	pTinten = NULL;	if (pTmerge)		free (pTmerge);	pTmerge = NULL;	if (pixel)		free (pixel);	pixel = NULL;	if (old_list)		free (old_list);	old_list = NULL;	if (new_list)		free (new_list);	new_list = NULL;}/* * draws an anti-aliased pixel (blends pixel with background) */INLINE void vector_draw_aa_pixel (int x, int y, int col, int dirty){	unsigned char *address;	if (x < xmin || x >= xmax)		return;	if (y < ymin || y >= ymax)		return;	address=&(vecbitmap->line[y][x]);	*address=(unsigned char)Tmerge(*address,(unsigned char)(col));	if (p_index<MAX_PIXELS)	{		pixel[p_index]=y | (x << 16);		p_index++;	}}/* * draws a line * * input:   x2  16.16 fixed point *          y2  16.16 fixed point *         col  0-255 indexed color (8 bit) *   intensity  0-255 intensity *       dirty  bool  mark the pixels as dirty while plotting them * * written by Andrew Caldwell */void vector_draw_to (int x2, int y2, int col, int intensity, int dirty){	unsigned char a1;	int orientation;	int dx,dy,sx,sy,cx,cy,width;	static int x1,yy1;	int xx,yy;	/* [1] scale coordinates to display */	x2 = vec_mult(x2<<4,vector_scale_x);	y2 = vec_mult(y2<<4,vector_scale_y);	/* [2] fix display orientation */	orientation = Machine->orientation;	if (orientation != ORIENTATION_DEFAULT)	{		if (orientation & ORIENTATION_SWAP_XY)		{			int temp;			temp = x2;			x2 = y2;			y2 = temp;		}		if (orientation & ORIENTATION_FLIP_X)			x2 = ((vecwidth-1)<<16)-x2;		if (orientation & ORIENTATION_FLIP_Y)			y2 = ((vecheight-1)<<16)-y2;	}	/* [3] adjust cords if needed */	if (antialias)	{		if(beam_diameter_is_one)		{			x2 = (x2+0x8000)&0xffff0000;			y2 = (y2+0x8000)&0xffff0000;

⌨️ 快捷键说明

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