📄 vgadisp.c
字号:
struct modedesc_tag *md_ptr;/* here's the plan; * - we try to keep the number of pixels as close as possible: * as this will probably be quite noticeable, *this takes priority*. * - we then try to match any 8-bit modes for EIGHT_BIT, or match * 24/16/15-bit modes (in that order) for HIGHCOLOUR. * - of course, the mode has to be either 8 or 15/16/24-bit as reqd. * * no support in this for 640x480x4 (16-colour) - because that's * a really weird special-case mode, you have to explicitly select it * if you want it. However, it sticks in 640x480x4 if selected and * modetype is FIX_TO_EIGHT_BIT, because it'd be totally annoying * otherwise. */if(curvgamode==G640x480x16 && modetype==FIX_TO_EIGHT_BIT) return;newmode=-1; pixdiff=(1<<30);numpixels=get_mode_width(curvgamode)*get_mode_height(curvgamode);/* account for effect of 'virtual' */if(curvgamode==G320x400x256 || curvgamode==G360x480x256) numpixels*=2;for(md_ptr=modedesc;md_ptr->mode;md_ptr++) { f=md_ptr->mode; if(!vga_hasmode(f) || cfg.mode_allowed[f]==0 || (vminfo=vga_getmodeinfo(f))==NULL) continue; mode_ok=0; if(modetype==FIX_TO_EIGHT_BIT) { if(vminfo->colors==256) mode_ok=1; } else { if(vminfo->colors>256) mode_ok=1; } if(mode_ok==0) continue; newnp=(vminfo->width)*(vminfo->height); if(f==G320x400x256 || f==G360x480x256) newnp*=2; /* account for effect of 'virtual' */ newdiff=numpixels-newnp; if(newdiff<0) newdiff=(-newdiff); if(newdiff<=pixdiff) { newmode=f; pixdiff=newdiff; } }/* we rely on the 15/16/32/24-bit mode number ordering to sort that * out for us (hence the `<=' above). */curvgamode=newmode;virtual=(curvgamode==G320x400x256 || curvgamode==G360x480x256);}int mode_ok_for_auto_switch(struct modedesc_tag *md_ptr){static int has640x480=-1;int f=md_ptr->mode;if(has640x480==-1) has640x480=(vga_hasmode(G640x480x256) && cfg.mode_allowed[G640x480x256]);if(!vga_hasmode(f) || cfg.mode_allowed[f]==0) return(0);/* don't use 320x200 modes (screwy aspect ratio). */if(md_ptr->width==320 && md_ptr->height==200) return(0); /* don't use 640x480x4 (too odd), or 320x400x8 (aspect ratio again). */if(f==G640x480x16 || f==G320x400x256) return(0);/* skip 360x480x8 if a 640x480x8 mode exists. */if(f==G360x480x256 && has640x480) return(0);/* obviously, has to be a compatible depth. */if((pixelsize==1 && md_ptr->bitspp!=8) || (pixelsize==3 && md_ptr->bitspp==8)) return(0);/* otherwise ok */return(1);}void do_auto_mode_fit(void){struct modedesc_tag *md_ptr;int w,h;int newmode=-1,newmode_w=(1<<30),newmode_h=(1<<30);int bigmode=-1,bigmode_w=0,bigmode_h=0;if(!cfg.automodefit) return;for(md_ptr=modedesc;md_ptr->mode;md_ptr++) { if(!mode_ok_for_auto_switch(md_ptr)) continue; w=md_ptr->width*(1+(md_ptr->mode==G360x480x256)); h=md_ptr->height; /* has to be >= pic size, but <= current best-fit mode. */ if(w>=width && h>=height && w<=newmode_w && h<=newmode_h) newmode=md_ptr->mode,newmode_w=w,newmode_h=h; /* also track biggest mode as backup in case no mode fits it all. */ if(w>=bigmode_w && h>=bigmode_h) bigmode=md_ptr->mode,bigmode_w=w,bigmode_h=h; }if(newmode==-1) { if(bigmode==-1) newmode=curvgamode; /* should be a can't-happen though */ else newmode=bigmode; }curvgamode=newmode;}/* arg is non-zero if want bigger mode, or zero if want smaller. * returns 0 if no mode fits. */int change_mode_size(int bigger){struct modedesc_tag *md_ptr;int w,h;int newmode=-1,diff,mindiff=(1<<30);for(md_ptr=modedesc;md_ptr->mode;md_ptr++) { if(!mode_ok_for_auto_switch(md_ptr)) continue; w=md_ptr->width*(1+(md_ptr->mode==G360x480x256)); h=md_ptr->height; if(bigger) { diff=(w-scrnwide)*(h-scrnhigh); /* the <= in the diff bit gives us the best depth available */ if(w>scrnwide && h>scrnhigh && diff<=mindiff) newmode=md_ptr->mode,mindiff=diff; } else { /* smaller */ diff=(scrnwide-w)*(scrnhigh-h); if(w<scrnwide && h<scrnhigh && diff<=mindiff) newmode=md_ptr->mode,mindiff=diff; } }if(newmode==-1) return(0);curvgamode=newmode;return(1);}void aborted_file_cleanup(){switch(loading_file_type) { case _IS_GIF: aborted_file_gif_cleanup(); break; case _IS_JPEG: aborted_file_jpeg_cleanup(); break; case _IS_PNM: aborted_file_pnm_cleanup(); break; case _IS_TIFF: aborted_file_tiff_cleanup(); break; case _IS_BMP: aborted_file_bmp_cleanup(); break; case _IS_TGA: aborted_file_tga_cleanup(); break; case _IS_PNG: aborted_file_png_cleanup(); break; case _IS_XVPIC: fprintf(stderr,"aborted xvpic load: can't happen!\n"); exit(1); case _IS_PCX: aborted_file_pcx_cleanup(); break; case _IS_MRF: aborted_file_mrf_cleanup(); break; case _IS_PRF: aborted_file_prf_cleanup(); break; case _IS_XBM: aborted_file_xbm_cleanup(); break;#ifdef PCD_SUPPORT case _IS_PCD: aborted_file_pcd_cleanup(); break;#endif case _IS_XPM: aborted_file_xpm_cleanup(); break; }}void makerealpal(){int f;int r,rlo,g,glo,b,blo;int gval;for(f=0;f<256;f++) { r=palr[f]>>2; rlo=palr[f]&3; g=palg[f]>>2; glo=palg[f]&3; b=palb[f]>>2; blo=palb[f]&3; if(cfg.fakecols) { gval=(rlo*grey_red+glo*grey_green+blo*grey_blue)/4; /* so gval is sub-value, 0<=gval<1000. (really <750... :-( ) * possible emulated sub-values are... * 0, 114 (b), 299 (r), 413 (r+b), 587 (g), 701 (g+b), 886 (r+g) */ if(gval>=886) r++,g++; else if(gval>=701) g++,b++; else if(gval>=587) g++; else if(gval>=413) r++,b++; else if(gval>=299) r++; else if(gval>=114) b++; if(r>63) r=63; if(g>63) g=63; if(b>63) b=63; } palrgb[f*3 ]=palr64[f]=r; palrgb[f*3+1]=palg64[f]=g; palrgb[f*3+2]=palb64[f]=b; }}void filterpal(byte *palette){int f;for(f=0;f<256;f++) /* don't *really* need to know number of colours */ { /* we also abuse this to get a brightness/contrast-ified index * to use for high-colour mode b/c. :-) (Hence palt[].) */ /* XXX it's debatable where gamma should be applied... */ if(cfg.bc_order_rev) { palr[f]=contrastup(dimmer(apply_gamma(palette[ f]))); palg[f]=contrastup(dimmer(apply_gamma(palette[256+f]))); palb[f]=contrastup(dimmer(apply_gamma(palette[512+f]))); palt[f]=contrastup(dimmer(apply_gamma(f))); } else { palr[f]=dimmer(contrastup(apply_gamma(palette[ f]))); palg[f]=dimmer(contrastup(apply_gamma(palette[256+f]))); palb[f]=dimmer(contrastup(apply_gamma(palette[512+f]))); palt[f]=dimmer(contrastup(apply_gamma(f))); } }makerealpal();}int dimmer(int a){a+=brightness;if(a<0) a=0;if(a>255) a=255;return(a);}int contrastup(int cp){float g;g=(float)(cp);g=128.+(g-128.)*contrast;if(g<0.) g=0.;if(g>255.) g=255.;return((int)g);}int apply_gamma(int val){int d16col=(curvgamode==G640x480x16 && cfg.viewer16col);/* the ==1.0 is a bit bogus, but likely to work if you've not * messed about with it too heavily - certainly it'll work if you * never changed it. :-) */if(picgamma==1.0 && !d16col) return(val);/* use 2.2 as a base, assuming most people will have gamma 2.2 monitors * (the 8-colour dither is inherently linear gamma in all cases). */if(d16col) return((int)(pow(val/255., 2.2/picgamma)*255.+0.5));return((int)(pow(val/255., 1./picgamma)*255.+0.5));}int get_mode_width(int vm){vga_modeinfo *vmi;vmi=vga_getmodeinfo(vm);return(vmi->width);}int get_mode_height(int vm){vga_modeinfo *vmi;vmi=vga_getmodeinfo(vm);return(vmi->height);}int get_mode_pixelbytes(int vm){vga_modeinfo *vmi;vmi=vga_getmodeinfo(vm);return(vmi->bytesperpixel);}int get_mode_numcols(int vm){vga_modeinfo *vmi;vmi=vga_getmodeinfo(vm);return(vmi->colors);}void do_16col_palette(){int paltmp[16*3],f,r,g,b;if(cfg.viewer16col) { /* colour */ for(f=r=0;r<2;r++) for(g=0;g<2;g++) for(b=0;b<2;b++,f+=3) paltmp[f]=r*63,paltmp[f+1]=g*63,paltmp[f+2]=b*63; /* FWIW, zero colours 8..15. It may seem wasteful not using these, * but there's no way I can see to use them as part of an ordered * dither which doesn't look awful (and error-diffused dithering * is too slow). */ for(;f<16*3;f+=3) paltmp[f]=paltmp[f+1]=paltmp[f+2]=0; /* actually, in that case, best to allocate some for right-button * menu colours! */ f=8; paltmp[f*3 ]=cfg.light.r; paltmp[f*3+1]=cfg.light.g; paltmp[f*3+2]=cfg.light.b; f++; paltmp[f*3 ]=cfg.medium.r; paltmp[f*3+1]=cfg.medium.g; paltmp[f*3+2]=cfg.medium.b; f++; paltmp[f*3 ]=cfg.dark.r; paltmp[f*3+1]=cfg.dark.g; paltmp[f*3+2]=cfg.dark.b; f++; paltmp[f*3 ]=cfg.black.r; paltmp[f*3+1]=cfg.black.g; paltmp[f*3+2]=cfg.black.b; }else { /* 16-grey palette */ for(f=0;f<16;f++) paltmp[f*3]=paltmp[f*3+1]=paltmp[f*3+2]=(f*63)/15; }vga_setpalvec(0,16,paltmp);}/* set new mode if needed, else just clear screen. */void setmode_or_clear(int newmode){if(vga_getcurrentmode()!=newmode) vga_setmode(newmode); else vga_clear();}void init_vkludge_cache(void){int x;/* invalidate any cached colours */memset(vkcache_valid,0,sizeof(vkcache_valid));/* the actual palette colours are fairly likely to crop up :-), * so index them automatically. */for(x=0;x<numcols;x++) closest(pal32_no_bc[x*3],pal32_no_bc[x*3+1],pal32_no_bc[x*3+2]);}void graphicson(void){msgbox_draw_ok=0;vga_lockvc();if((vga_hasmode(curvgamode))&&(cfg.mode_allowed[curvgamode])) setmode_or_clear(curvgamode);else { /* we haven't? Aaargh!!! Ok, use 640x480 or 360x480 instead. */ if((vga_hasmode(G640x480x256))&&(cfg.mode_allowed[G640x480x256])) setmode_or_clear(curvgamode=G640x480x256); else { if((vga_hasmode(G360x480x256))&&(cfg.mode_allowed[G360x480x256])) setmode_or_clear(curvgamode=G360x480x256); else /* *must* have 320x200 (see rcfile.c for more info) */ setmode_or_clear(curvgamode=G320x200x256); } }virtual=0;if(curvgamode==G320x400x256 || curvgamode==G360x480x256) virtual=1;if(curvgamode==G640x480x16) do_16col_palette();if(pixelsize!=1) gl_setcontextvga(curvgamode);scrnwide=get_mode_width(curvgamode);scrnhigh=get_mode_height(curvgamode);scrnpixelsize=get_mode_pixelbytes(curvgamode);scrncols=get_mode_numcols(curvgamode);if(virtual) scrnwide*=2;if(pixelsize==1) setpalvec(0,256,palrgb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -