/* SCCS Id: @(#)jtp_gra.c 3.0 2000/11/12 */ /* Copyright (c) Jaakko Peltonen, 2000 */ /* NetHack may be freely redistributed. See license for details. */ #ifndef _jtp_gra_c_ #define _jtp_gra_c_ #include "jtp_def.h" #include #include #include #ifdef USE_DIRECTX_SYSCALLS #include "jtp_dirx.h" #endif #ifdef USE_DOS_SYSCALLS #include "jtp_dos.h" #endif #include "jtp_gen.h" #include "jtp_gra.h" unsigned char jtp_colors[256][3]; jtp_screen_t jtp_screen; double jtp_gamma_correction = 1.0; /*----------------------------------------- Interface to system dependent functions -----------------------------------------*/ void jtp_enter_graphics_mode() { #ifdef USE_DIRECTX_SYSCALLS jtp_DXEnterGraphicsMode(&jtp_screen); #endif #ifdef USE_DOS_SYSCALLS jtp_DOSEnterGraphicsMode(&jtp_screen); #endif #ifdef USE_SDL_SYSCALLS jtp_SDLEnterGraphicsMode(&jtp_screen); #endif } void jtp_exit_graphics_mode() { #ifdef USE_DIRECTX_SYSCALLS jtp_DXExitGraphicsMode(&jtp_screen); #endif #ifdef USE_DOS_SYSCALLS jtp_DOSExitGraphicsMode(&jtp_screen); #endif #ifdef USE_SDL_SYSCALLS jtp_SDLExitGraphicsMode(&jtp_screen); #endif } void jtp_palch ( unsigned char cindex, unsigned char r, unsigned char g, unsigned char b ) { #ifdef USE_DIRECTX_SYSCALLS jtp_DXRecordColor(cindex, r, g, b); jtp_DXSetPalette(); #endif #ifdef USE_DOS_SYSCALLS jtp_DOSSetColor(cindex, r, g, b); #endif #ifdef USE_SDL_SYSCALLS jtp_SDLRecordColor(cindex, r, g, b); jtp_SDLSetPalette(); #endif } void jtp_refresh() { #ifdef USE_DIRECTX_SYSCALLS jtp_DXRefresh(&jtp_screen); #endif #ifdef USE_DOS_SYSCALLS jtp_DOSRefresh(&jtp_screen); #endif #ifdef USE_SDL_SYSCALLS jtp_SDLRefresh(&jtp_screen); #endif } void jtp_refresh_region(int x1, int y1, int x2, int y2) { #ifdef USE_DIRECTX_SYSCALLS jtp_DXRefreshRegion(x1, y1, x2, y2, &jtp_screen); #endif #ifdef USE_DOS_SYSCALLS jtp_DOSRefreshRegion(x1, y1, x2, y2, &jtp_screen); #endif #ifdef USE_SDL_SYSCALLS jtp_SDLRefreshRegion(x1, y1, x2, y2, &jtp_screen); #endif } /*----------------------------------------- Graphics initialization ------------------------------------------*/ void jtp_fill_ifcolors ( unsigned char *ifcolors ) { int i; for (i = 0; i < 256; i++) ifcolors[i] = i; } void jtp_init_screen ( int screen_width, int screen_height, int screen_bit_depth ) { jtp_screen.width = screen_width; jtp_screen.height = screen_height; jtp_screen.vpage = (unsigned char *)calloc(jtp_screen.width*jtp_screen.height,sizeof(unsigned char)); jtp_screen.drx1 = 0; jtp_screen.dry1 = 0; jtp_screen.drx2 = jtp_screen.width-1; jtp_screen.dry2 = jtp_screen.height-1; } void jtp_free_screen() { free(jtp_screen.vpage); } /*-------------------------------------------------------------------------- Palette handling --------------------------------------------------------------------------*/ void jtp_correct_gamma ( unsigned char *r, /* Pointers to the color components to be corrected */ unsigned char *g, unsigned char *b, double alpha /* Gamma value, alpha > 0. Values below 1 darken. */ ) { double l; /* Original color luminosity */ double m; /* Gamma correction multiplier */ /* * A simple "L1" or "city-block" norm is used here * to calculate luminosity. Other norms could also * be used, for example the "L2" norm, or some * weighted version of these. Also the relative * importance of the red/green/blue components * could be weighted. */ l = ((double)*r + (double)*g + (double)*b) / (3.0*63.0); if (l == 0) return; /* Gamma correct luminosity value */ if (alpha <= 0) return; if (alpha > 0) alpha = 1.0/alpha; m = 1/((1-alpha*alpha)*l+alpha*alpha); /* Correct the red, green and blue values */ l = *r * m; if (l > 63) l = 63; *r = l; l = *g * m; if (l > 63) l = 63; *g = l; l = *b * m; if (l > 63) l = 63; *b = l; return; } void jtp_updatepal ( unsigned char index1, unsigned char index2 ) { int i; #ifdef USE_DIRECTX_SYSCALLS for (i = index1; i <= index2; i++) jtp_DXRecordColor(i, jtp_colors[i][0], jtp_colors[i][1], jtp_colors[i][2]); jtp_DXSetPalette(); jtp_DXProcessEvents(); #endif #ifdef USE_DOS_SYSCALLS for (i = index1; i <= index2; i++) jtp_DOSSetColor(i, jtp_colors[i][0], jtp_colors[i][1], jtp_colors[i][2]); #endif #ifdef USE_SDL_SYSCALLS for (i = index1; i <= index2; i++) jtp_SDLRecordColor(i, jtp_colors[i][0], jtp_colors[i][1], jtp_colors[i][2]); jtp_SDLSetPalette(); jtp_SDLProcessEvents(); #endif } void jtp_blankpal ( unsigned char index1, unsigned char index2 ) { int i; #ifdef USE_DIRECTX_SYSCALLS for (i = index1; i <= index2; i++) jtp_DXRecordColor(i, 0, 0, 0); jtp_DXSetPalette(); jtp_DXProcessEvents(); #endif #ifdef USE_DOS_SYSCALLS for (i = index1; i <= index2; i++) jtp_DOSSetColor(i, 0, 0, 0); #endif #ifdef USE_SDL_SYSCALLS for (i = index1; i <= index2; i++) jtp_SDLRecordColor(i, 0, 0, 0); jtp_SDLSetPalette(); jtp_SDLProcessEvents(); #endif } void jtp_fade_out(double n_secs) { clock_t start_clock, cur_clock, old_clock, n_clocks; int i; n_clocks = CLOCKS_PER_SEC*n_secs; start_clock = clock(); cur_clock = start_clock; old_clock = cur_clock; while (cur_clock < n_clocks + start_clock) { if (cur_clock != old_clock) { #ifdef USE_DIRECTX_SYSCALLS for (i = 0; i < 256; i++) jtp_DXRecordColor(i, (jtp_colors[i][0]*(n_clocks+start_clock-cur_clock))/n_clocks, (jtp_colors[i][1]*(n_clocks+start_clock-cur_clock))/n_clocks, (jtp_colors[i][2]*(n_clocks+start_clock-cur_clock))/n_clocks); jtp_DXSetPalette(); jtp_DXProcessEvents(); #endif #ifdef USE_DOS_SYSCALLS for (i = 0; i < 256; i++) jtp_DOSSetColor(i, (jtp_colors[i][0]*(n_clocks+start_clock-cur_clock))/n_clocks, (jtp_colors[i][1]*(n_clocks+start_clock-cur_clock))/n_clocks, (jtp_colors[i][2]*(n_clocks+start_clock-cur_clock))/n_clocks); #endif #ifdef USE_SDL_SYSCALLS for (i = 0; i < 256; i++) jtp_SDLRecordColor(i, (jtp_colors[i][0]*(n_clocks+start_clock-cur_clock))/n_clocks, (jtp_colors[i][1]*(n_clocks+start_clock-cur_clock))/n_clocks, (jtp_colors[i][2]*(n_clocks+start_clock-cur_clock))/n_clocks); jtp_SDLSetPalette(); jtp_SDLProcessEvents(); #endif } old_clock = cur_clock; cur_clock = clock(); } jtp_blankpal(0,255); } void jtp_fade_in(double n_secs) { clock_t start_clock, cur_clock, old_clock, n_clocks; int i; n_clocks = CLOCKS_PER_SEC*n_secs; start_clock = clock(); cur_clock = start_clock; old_clock = cur_clock; while (cur_clock < n_clocks + start_clock) { if (cur_clock != old_clock) { #ifdef USE_DIRECTX_SYSCALLS for (i = 0; i < 256; i++) jtp_DXRecordColor(i, (jtp_colors[i][0]*(cur_clock-start_clock))/n_clocks, (jtp_colors[i][1]*(cur_clock-start_clock))/n_clocks, (jtp_colors[i][2]*(cur_clock-start_clock))/n_clocks); jtp_DXSetPalette(); jtp_DXProcessEvents(); #endif #ifdef USE_DOS_SYSCALLS for (i = 0; i < 256; i++) jtp_DOSSetColor(i, (jtp_colors[i][0]*(cur_clock-start_clock))/n_clocks, (jtp_colors[i][1]*(cur_clock-start_clock))/n_clocks, (jtp_colors[i][2]*(cur_clock-start_clock))/n_clocks); #endif #ifdef USE_SDL_SYSCALLS for (i = 0; i < 256; i++) jtp_SDLRecordColor(i, (jtp_colors[i][0]*(cur_clock-start_clock))/n_clocks, (jtp_colors[i][1]*(cur_clock-start_clock))/n_clocks, (jtp_colors[i][2]*(cur_clock-start_clock))/n_clocks); jtp_SDLSetPalette(); jtp_SDLProcessEvents(); #endif } old_clock = cur_clock; cur_clock = clock(); } jtp_updatepal(0,255); } /*-------------------------------------------------------------------------- Basic graphics plotting --------------------------------------------------------------------------*/ void jtp_set_draw_region ( int _drx1, int _dry1, int _drx2, int _dry2 ) { if (_drx1 >= 0) jtp_screen.drx1=_drx1; else jtp_screen.drx1 = 0; if (_dry1 >= 0) jtp_screen.dry1=_dry1; else jtp_screen.dry1 = 0; if (_drx2 < jtp_screen.width) jtp_screen.drx2=_drx2; else jtp_screen.drx2 = jtp_screen.width-1; if (_dry2 < jtp_screen.height) jtp_screen.dry2=_dry2; else jtp_screen.dry2 = jtp_screen.height-1; } void jtp_pixelput ( int x, int y, unsigned char vari ) { jtp_screen.vpage[y*jtp_screen.width+x]=vari; } unsigned char jtp_pixelget(int x, int y) { return(jtp_screen.vpage[y*jtp_screen.width+x]); } void jtp_rect ( int x1, int y1, int x2, int y2, unsigned char cindex ) { int i,j; for (i = x1; i <= x2; i++) { jtp_screen.vpage[y1*jtp_screen.width+i] = cindex; jtp_screen.vpage[y2*jtp_screen.width+i] = cindex; } for (j = y1; j <= y2; j++) { jtp_screen.vpage[j*jtp_screen.width+x1] = cindex; jtp_screen.vpage[j*jtp_screen.width+x2] = cindex; } } void jtp_fill_rect ( int x1, int y1, int x2, int y2, unsigned char cindex ) { int i,j; if (x1 < jtp_screen.drx1) x1 = jtp_screen.drx1; if (y1 < jtp_screen.dry1) y1 = jtp_screen.dry1; if (x2 > jtp_screen.drx2) x2 = jtp_screen.drx2; if (y2 > jtp_screen.dry2) y2 = jtp_screen.dry2; for (i = x1; i <= x2; i++) for (j = y1; j <= y2; j++) jtp_screen.vpage[j*jtp_screen.width+i] = cindex; } void jtp_bres_line ( int x1, int y1, int x2, int y2, unsigned char cindex ) { int dx, dy, x, y, tmpplus, endx, endy, p, const1, const2; dx = abs(x1-x2); dy = abs(y1-y2); if (dx > dy) { p = 2*dy-dx; const1 = 2*dy; const2 = 2*(dy-dx); if (x1 > x2) { x = x2; y = y2; endx = x1; if (y1 > y2) tmpplus = 1; else tmpplus = -1; } else { x = x1; y = y1; endx = x2; if (y2 > y1) tmpplus = 1; else tmpplus = -1; } jtp_screen.vpage[jtp_screen.width*y+x] = cindex; while (x < endx) { if (p < 0) p += const1; else { y += tmpplus; p += const2; } x++; jtp_screen.vpage[jtp_screen.width*y+x] = cindex; } } else { p = 2*dx-dy; const1 = 2*dx; const2 = 2*(dx-dy); if (y1 > y2) { y = y2; x = x2; endy = y1; if (x1 > x2) tmpplus = 1; else tmpplus = -1; } else { y = y1; x = x1; endy = y2; if (x2 > x1) tmpplus = 1; else tmpplus = -1; } jtp_screen.vpage[jtp_screen.width*y+x] = cindex; while (y < endy) { if (p < 0) p += const1; else { x += tmpplus; p += const2; } y++; jtp_screen.vpage[jtp_screen.width*y+x] = cindex; } } } void jtp_bres_circle_points ( int xc, int yc, int dx, int dy, unsigned char cindex ) { int tempofs; tempofs = jtp_screen.width*(yc+dy)+xc; jtp_screen.vpage[tempofs-dx] = cindex; jtp_screen.vpage[tempofs+dx] = cindex; tempofs = jtp_screen.width*(yc-dy)+xc; jtp_screen.vpage[tempofs-dx] = cindex; jtp_screen.vpage[tempofs+dx] = cindex; tempofs = jtp_screen.width*(yc+dx)+xc; jtp_screen.vpage[tempofs-dy] = cindex; jtp_screen.vpage[tempofs+dy] = cindex; tempofs = jtp_screen.width*(yc-dx)+xc; jtp_screen.vpage[tempofs-dy] = cindex; jtp_screen.vpage[tempofs+dy] = cindex; } void jtp_bres_circle ( int xc, int yc, int radius, unsigned char cindex ) { int x, y, p; x = 0; y = radius; p = 3 - 2*radius; while (x < y) { jtp_bres_circle_points(xc, yc, x, y, cindex); if (p < 0) p += x*4 + 6; else { p += (x-y)*4 + 10; y--; } x++; } if (x==y) jtp_bres_circle_points(xc, yc, x, y, cindex); } void jtp_bres_circle_lines ( int xc, int yc, int dx, int dy, unsigned char cindex ) { int tempofs,i; tempofs = jtp_screen.width*(yc+dy)+xc; for (i=-dx; i <= dx; i++) jtp_screen.vpage[tempofs+i] = cindex; tempofs = jtp_screen.width*(yc-dy)+xc; for (i=-dx; i <= dx; i++) jtp_screen.vpage[tempofs+i] = cindex; tempofs = jtp_screen.width*(yc+dx)+xc; for (i=-dy; i <= dy; i++) jtp_screen.vpage[tempofs+i] = cindex; tempofs = jtp_screen.width*(yc-dx)+xc; for (i=-dy; i <= dy; i++) jtp_screen.vpage[tempofs+i] = cindex; } void jtp_bres_fill_circle ( int xc, int yc, int radius, unsigned char cindex ) { int x, y, p, i; x = 0; y = radius; p = 3 - 2*radius; /* for (i=-y; i <= y; i++) { jtp_screen.vpage[jtp_screen.width*yc+xc+i]++; } */ while (x < y) { if (p < 0) p += x*4 + 6; else { p += (x-y)*4 + 10; y--; for (i=-x; i <= x; i++) { jtp_screen.vpage[jtp_screen.width*(yc+y)+xc+i]++;/* = cindex;*/ jtp_screen.vpage[jtp_screen.width*(yc-y)+xc+i]++;/* = cindex;*/ } } if (x!=y) for (i=-y; i <= y; i++) { jtp_screen.vpage[jtp_screen.width*(yc+x)+xc+i]++;/* = cindex;*/ jtp_screen.vpage[jtp_screen.width*(yc-x)+xc+i]++;/* = cindex;*/ } x++; } /* if (x==y) bres_circle_lines(xc,yc,x,y,cindex); */ } /*-------------------------------------------------------------------------- Bitmap handling --------------------------------------------------------------------------*/ unsigned char *jtp_get_img ( int x1, int y1, int x2, int y2 ) { int Xsize,Ysize,i; int Xbegin, Ybegin; unsigned char *a; if (x1>jtp_screen.width-1) return(NULL); if (y1>jtp_screen.height-1) return(NULL); if (x2<0) return(NULL); if (y2<0) return(NULL); if (x1<0) Xbegin = -x1; else Xbegin = 0; if (y1<0) Ybegin = -y1; else Ybegin = 0; if (x2>jtp_screen.width-1) x2=jtp_screen.width-1; if (y2>jtp_screen.height-1) y2=jtp_screen.height-1; Ysize=y2-y1+1; Xsize=x2-x1+1; a=(unsigned char *)malloc((Ysize*Xsize+4)*sizeof(unsigned char)); if (a==NULL) return(NULL); a[0]=Ysize >> 8; a[1]=Ysize & 255; a[2]=Xsize >> 8; a[3]=Xsize & 255; for (i=Ybegin;i<=Ysize-1;i++) memcpy(&(a[i*Xsize+4+Xbegin]),&(jtp_screen.vpage[(y1+i)*jtp_screen.width+x1+Xbegin]),Xsize-Xbegin); return(a); } unsigned char *jtp_get_img_src ( int x1, int y1, int x2, int y2, unsigned char *img_source ) { int Xsize,Ysize,i; int imgXsize,imgYsize; unsigned char *a; if (!img_source) return(NULL); imgYsize=img_source[0]*256+img_source[1]; imgXsize=img_source[2]*256+img_source[3]; if (x1>imgXsize-1) return(NULL); if (y1>imgYsize-1) return(NULL); if (x2<0) return(NULL); if (y2<0) return(NULL); if (x1<0) x1=0; if (y1<0) y1=0; if (x2>imgXsize-1) x2=imgXsize-1; if (y2>imgYsize-1) y2=imgYsize-1; Ysize=y2-y1+1; Xsize=x2-x1+1; a=(unsigned char *)malloc((Ysize*Xsize+4)*sizeof(unsigned char)); if (a==NULL) return(NULL); a[0]=Ysize >> 8; a[1]=Ysize & 255; a[2]=Xsize >> 8; a[3]=Xsize & 255; img_source+=y1*imgXsize + x1 + 4; for (i=0;i<=Ysize-1;i++) { memcpy(&(a[i*Xsize+4]),img_source,Xsize); img_source+=imgXsize; } return(a); } void jtp_put_img ( int x, int y, unsigned char *a ) { int srcXsize,cutXsize,srcYsize,i,y1,y2,x1; unsigned char *destin; if ((a==NULL) || (x>jtp_screen.drx2) || (y>jtp_screen.dry2)) return; srcYsize=a[0]*256+a[1]; srcXsize=a[2]*256+a[3]; if ((x+srcXsize<=jtp_screen.drx1) || (y+srcYsize<=jtp_screen.dry1)) return; if (yjtp_screen.dry2) y2=jtp_screen.dry2-y; else y2=srcYsize-1; if (x+srcXsize-1>jtp_screen.drx2) cutXsize=jtp_screen.drx2-x+1; else cutXsize=srcXsize; if (xjtp_screen.drx2) || (y>jtp_screen.dry2)) return; srcYsize=a[0]*256+a[1]; srcXsize=a[2]*256+a[3]; if ((x+srcXsize<=jtp_screen.drx1) || (y+srcYsize<=jtp_screen.dry1)) return; if (yjtp_screen.dry2) y2=jtp_screen.dry2-y; else y2=srcYsize-1; if (xjtp_screen.drx2) x2=jtp_screen.drx2-x; else x2=srcXsize-1; a+=y1*srcXsize+4; a_end = a + (y2-y1+1)*srcXsize; destin=jtp_screen.vpage+(y1+y)*jtp_screen.width+x; dplus = jtp_screen.width; a += x1; a_end += x1; destin += x1; x2 -= x1; x1 = jtp_screen.width; while (a < a_end) { for (j = x2; j >= 0; j--) { /* vari=a[j]; if (vari!=0) destin[j]=vari; */ if (a[j]) destin[j] = a[j]; } a += srcXsize; destin += dplus; } } #endif