📄 svgalib.c
字号:
#endif#ifdef G1920x1440x16M {"1920x1440x16M", G1920x1440x16M },#endif#ifdef G1920x1440x16M32 {"1920x1440x16M32", G1920x1440x16M32 },#endif#ifdef G2048x1152x256 {"2048x1152x256", G2048x1152x256 },#endif#ifdef G2048x1152x32K {"2048x1152x32K", G2048x1152x32K },#endif#ifdef G2048x1152x64K {"2048x1152x64K", G2048x1152x64K },#endif#ifdef G2048x1152x16M {"2048x1152x16M", G2048x1152x16M },#endif#ifdef G2048x1152x16M32 {"2048x1152x16M32", G2048x1152x16M32 },#endif#ifdef G2048x1536x256 {"2048x1536x256", G2048x1536x256 },#endif#ifdef G2048x1536x32K {"2048x1536x32K", G2048x1536x32K },#endif#ifdef G2048x1536x64K {"2048x1536x64K", G2048x1536x64K },#endif#ifdef G2048x1536x16M {"2048x1536x16M", G2048x1536x16M },#endif#ifdef G2048x1536x16M32 {"2048x1536x16M32", G2048x1536x16M32 },#endif};/*--------------------------- ROUTINES ---------------------------------------*//* Generates these palettes: * 7 6 5 4 3 2 1 0 * +-----+-----+---+ * | R | G | B | * +-----+-----+---+ * * * 3 2 1 0 * +-+---+-+ * |R| G |B| * +-+---+-+ */static void show_mouse(void);static void hide_mouse(void);static void redraw_mouse(void);/* We must perform a quirkafleg * This is an empiric magic that ensures * Good white purity * Correct rounding and dithering prediction * And this is the cabbala: * 063 021 063 * 009 009 021 * 255 085 255 * 036 036 084 */static void generate_palette(struct irgb *palette){ int a; if (vga_colors==16){ if (palette_depth==6){ for (a=0;a<16;a++,palette++) { palette->r=(a&8)?63:0; palette->g=((a>>1)&3)*21; palette->b=(a&1)?63:0; } }else{ /* palette_depth==8 */ for (a=0;a<16;a++,palette++) { palette->r=(a&8)?255:0; palette->g=((a>>1)&3)*85; palette->b=(a&1)?255:0; } } }else{ /* vga_colors==256 */ if (palette_depth==6){ for (a=0;a<256;a++,palette++){ palette->r=((a>>5)&7)*9; palette->g=((a>>2)&7)*9; palette->b=(a&3)*21; } }else{ /* palette_depth==8 */ for (a=0;a<256;a++,palette++){ palette->r=((a>>5)&7)*36; palette->g=((a>>2)&7)*36; palette->b=(a&3)*84; } } } }static void set_palette(struct irgb *palette){ int r,g,b,c; for (c=0;c<vga_colors;c++){ r=palette[c].r; g=palette[c].g; b=palette[c].b; vga_setpalette(c,r,g,b); }}static void svga_shutdown_driver(void){ if (scroll_buffer) mem_free(scroll_buffer); if (mouse_works){ mem_free(mouse_buffer); mem_free(background_buffer); mem_free(new_background_buffer); svga_driver.shutdown_device(mouse_graphics_device); mouse_close(); mouse_works=0; /* To keep vga_select disabled */ } shutdown_virtual_devices(); vga_unlockvc();#ifndef __SPAD__ kill_timer(svgalib_timer_id);#endif vga_setmode(TEXT); svgalib_free_trm(ditrm); if (svga_driver_param)mem_free(svga_driver_param); install_signal_handler(SIGINT, NULL, NULL, 0);}static void svga_register_bitmap(struct bitmap *bmp){}static void svga_unregister_bitmap(struct bitmap *bmp){ mem_free(bmp->data);}#define SYNC if (do_sync) vga_accel(ACCEL_SYNC); /* This assures that x, y, xs, ys, data will be sane according to clipping * rectangle. If nothing lies within this rectangle, the current function * returns. The data pointer is automatically advanced by this macro to reflect * the right position to start with inside the bitmap. */#define CLIP_PREFACE \ int xs=hndl->x,ys=hndl->y;\ char *data=hndl->data;\ int mouse_hidden;\\ TEST_INACTIVITY\ if (x>=dev->clip.x2||x+xs<=dev->clip.x1) return;\ if (y>=dev->clip.y2||y+ys<=dev->clip.y1) return;\ if (x+xs>dev->clip.x2) xs=dev->clip.x2-x;\ if (y+ys>dev->clip.y2) ys=dev->clip.y2-y;\ if (dev->clip.x1-x>0){\ xs-=(dev->clip.x1-x);\ data+=bmpixelsize*(dev->clip.x1-x);\ x=dev->clip.x1;\ }\ if (dev->clip.y1-y>0){\ ys-=(dev->clip.y1-y);\ data+=hndl->skip*(dev->clip.y1-y);\ y=dev->clip.y1;\ }\ /* xs, ys: how much pixels to paint\ * data: where to start painting from\ */\ TEST_MOUSE (x,x+xs,y,y+ys)static inline void draw_bitmap_accel(struct graphics_device *dev, struct bitmap* hndl, int x, int y){ CLIP_PREFACE if (xs*bmpixelsize==hndl->skip) vga_accel(ACCEL_PUTIMAGE,x,y,xs,ys,data); else for(;ys;ys--){ vga_accel(ACCEL_PUTIMAGE,x,y,xs,1,data); data+=hndl->skip; y++; } END_MOUSE}static inline void my_setpage(int page){ if (vga_page!=page){ vga_page=page; vga_setpage(page); }}static inline void paged_memcpy(int lina, unsigned char *src, int len){ int page=lina>>16; int paga=lina&0xffff; int remains; my_setpage(page); remains=65536-paga; again: if (remains>=len){ memcpy(my_graph_mem+paga,src,len); vga_page=page; return; }else{ memcpy(my_graph_mem+paga,src,remains); paga=0; src+=remains; len-=remains; remains=65536; vga_setpage(++page); goto again; }}static inline void draw_bitmap_drawscansegment(struct graphics_device *dev, struct bitmap* hndl, int x, int y){ int ys0; CLIP_PREFACE SYNC for (ys0=ys;ys0;ys0--){ vga_drawscansegment(data,x,y,xs); y++; data+=hndl->skip; } END_MOUSE}static inline void draw_bitmap_paged(struct graphics_device *dev, struct bitmap* hndl, int x, int y){ int scr_start; CLIP_PREFACE scr_start=y*vga_linewidth+x*vga_bytes; SYNC for(;ys;ys--){ paged_memcpy(scr_start,data,xs*vga_bytes); data+=hndl->skip; scr_start+=vga_linewidth; } END_MOUSE }static inline void draw_bitmap_linear(struct graphics_device *dev,struct bitmap* hndl, int x, int y){ unsigned char *scr_start; CLIP_PREFACE SYNC scr_start=my_graph_mem+y*vga_linewidth+x*vga_bytes; for(;ys;ys--){ memcpy(scr_start,data,xs*vga_bytes); data+=hndl->skip; scr_start+=vga_linewidth; } END_MOUSE}/* fill_area: 5,5,10,10 fills in 25 pixels! *//* This assures that left, right, top, bottom will be sane according to the * clipping rectangle set up by svga_driver->set_clip_area. If empty region * results, return from current function occurs. */#define FILL_CLIP_PREFACE \ int mouse_hidden;\ TEST_INACTIVITY\ if (left>=right||top>=bottom) return;\ if (left>=dev->clip.x2||right<=dev->clip.x1||top>=dev->clip.y2||bottom<=dev->clip.y1) return;\ if (left<dev->clip.x1) left=dev->clip.x1;\ if (right>dev->clip.x2) right=dev->clip.x2;\ if (top<dev->clip.y1) top=dev->clip.y1;\ if (bottom>dev->clip.y2) bottom=dev->clip.y2;\ TEST_MOUSE(left,right,top,bottom) static void fill_area_accel_box(struct graphics_device *dev, int left, int top, int right, int bottom, long color){ FILL_CLIP_PREFACE vga_accel(ACCEL_SETFGCOLOR,color); vga_accel(ACCEL_FILLBOX,left,top,right-left,bottom-top); END_MOUSE} static void fill_area_accel_lines(struct graphics_device *dev, int left, int top, int right, int bottom, long color){ int y; FILL_CLIP_PREFACE vga_accel(ACCEL_SETFGCOLOR,color); for (y=top;y<bottom;y++) vga_accel(ACCEL_DRAWLINE,left,y,right-1,y); END_MOUSE}/* n is in bytes. dest must begin on pixel boundary. If n is not a whole number * of pixels, rounding is performed downwards. * if bmpixelsize is 1, no alignment is required. * if bmpixelsize is 2, dest must be aligned to 2 bytes. * if bmpixelsize is 3, no alignment is required. * if bmpixelsize is 4, dest must be aligned to 4 bytes. * -- The following do not occur, this is only for forward compatibility. * if bmpixelsize is 5, no alignment is required. * if bmpixelsize is 6, dest must be aligned to 2 bytes. * if bmpixelsize is 7, no alignment is required. * if bmpixelsize is 8, dest must be aligned to 8 bytes. */static inline void pixel_set(unsigned char *dest, int n,void * pattern){ int a; /* Originally there was vga_bytes here but this function is not * used in planar modes so that it's OK :-) */ switch(bmpixelsize) { case 1: memset(dest,*(char *)pattern,n); break; case 2: {#ifdef t2c t2c v=*(t2c *)pattern; int a;#else unsigned char c1=*(unsigned char *)pattern ,c2=((unsigned char *)pattern)[1];#endif /* #ifdef t2c */ n>>=1;#ifdef t2c /* [] is here because i386 has built-in address doubling * that costs nothing and we spare a register and * an addition of 2 */ for (a=0;a<n;a++) ((t2c *)dest)[a]=v;#else for (;n;n--,dest+=2){ *dest=c1; dest[1]=c2; } #endif /* #ifdef t2c */ } break; case 3: { unsigned char a,b,c; a=*(unsigned char *)pattern; b=((unsigned char *)pattern)[1]; c=((unsigned char *)pattern)[2]; for (n/=3;n;n--){ dest[0]=a; dest[1]=b; dest[2]=c; dest+=3; } } break; case 4: {#ifdef t4c t4c v=*(t4c *)pattern; int a;#else unsigned char c1, c2, c3, c4; c1=*((unsigned char *) pattern); c2=((unsigned char *) pattern)[1]; c3=((unsigned char *) pattern)[2]; c4=((unsigned char *) pattern)[3];#endif /* #ifdef t4c */ n>>=2;#ifdef t4c /* [] is here because i386 has built-in address * quadrupling that costs nothing and we spare a * register and an addition of 4 */ for (a=0;a<n;a++) ((t4c *)dest)[a]=v;#else for (;n;n--, dest+=4){ *dest=c1; dest[1]=c2; dest[2]=c3; dest[3]=c4; } #endif /* #ifdef t4c */ } break; default: for (a=0;a<n/bmpixelsize;a++,dest+=bmpixelsize) memcpy(dest,pattern,bmpixelsize); break; } }static void fill_area_linear(struct graphics_device *dev, int left, int top, int right, int bottom, long color){ unsigned char *dest; int y; FILL_CLIP_PREFACE SYNC dest=my_graph_mem+top*vga_linewidth+left*vga_bytes; for (y=bottom-top;y;y--){ pixel_set(dest,(right-left)*vga_bytes,&color); dest+=vga_linewidth; } END_MOUSE}/* Params are exactly the same as in pixel_set except lina, which is offset from * my_graph_mem in bytes. Works for every vga_bytes. len is in bytes. len must * be a whole number of pixels. */static void pixel_set_paged(int lina, int len, void * color){ int page=lina>>16; /* Page number */ int paga=lina&0xffff; /* 16-bit address within a page */ int remains=65536-paga; /* How many bytes remain within the page*/ int offset=0; /* Offset inside the pixel */ unsigned char color0[15]; memcpy(color0,color,vga_bytes); memcpy(color0+vga_bytes,color,vga_bytes-1); my_setpage(page); again: if (remains>=len){ int done=len-len%vga_bytes; pixel_set(my_graph_mem+paga,done,color0+offset); paga+=done; if (done<len) memcpy(my_graph_mem+paga,color0+offset,len-done); vga_page=page; return; }else{ int done=remains-remains%vga_bytes; pixel_set(my_graph_mem+paga,done,color0+offset); paga+=done; if (done<remains) memcpy(my_graph_mem+paga,color0+offset,remains-done); offset+=(remains-done); if (offset>=vga_bytes) offset-=vga_bytes; len-=remains; remains=65536; vga_setpage(++page); paga=0; goto again; }}static void fill_area_paged(struct graphics_device *dev, int left, int top, int right, int bottom, long color){ int dest; int y; int len; FILL_CLIP_PREFACE SYNC len=(right-left)*vga_bytes; dest=top*vga_linewidth+left*vga_bytes; for (y=bottom-top;y;y--){ pixel_set_paged(dest,len,&color); dest+=vga_linewidth; } END_MOUSE} #define HLINE_CLIP_PREFACE \ int mouse_hidden;\ TEST_INACTIVITY\ if (left>=right) return;\ if (y<dev->clip.y1||y>=dev->clip.y2||right<=dev->clip.x1||left>=dev->clip.x2) return;\ if (left<dev->clip.x1) left=dev->clip.x1;\ if (right>dev->clip.x2) right=dev->clip.x2;\ TEST_MOUSE (left,right,y,y+1) #define VLINE_CLIP_PREFACE \ int mouse_hidden;\ TEST_INACTIVITY\ if (top>=bottom) return;\ if (x<dev->clip.x1||x>=dev->clip.x2||top>=dev->clip.y2||bottom<=dev->clip.y1) return;\ if (top<dev->clip.y1) top=dev->clip.y1;\ if (bottom>dev->clip.y2) bottom=dev->clip.y2;\ TEST_MOUSE(x,x+1,top,bottom) static void draw_hline_accel_line(struct graphics_device *dev, int left, int y, int right, long color){ HLINE_CLIP_PREFACE vga_accel(ACCEL_SETFGCOLOR,color); vga_accel(ACCEL_DRAWLINE,left,y,right-1,y); END_MOUSE}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -