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 + -
显示快捷键?