#include #include #include #include #if defined(OGLR) #ifdef MACOSX #include #include #include #elif defined(WIN32) #include #include #include #else #include #include #endif #endif #include "Config.h" //#include "simulation/Air.h" //#include "simulation/Gravity.h" //#include "powder.h" //#define INCLUDE_PSTRUCT //#include "Simulation.h" //#include "Graphics.h" //#include "ElementGraphics.h" #define INCLUDE_FONTDATA #include "font.h" #include "Misc.h" #include "hmap.h" //unsigned cmode = CM_FIRE; unsigned int *render_modes; unsigned int render_mode; unsigned int colour_mode; unsigned int *display_modes; unsigned int display_mode; //SDL_Surface *sdl_scrn; int sdl_scale = 1; #ifdef OGLR GLuint zoomTex, vidBuf, airBuf, fireAlpha, glowAlpha, blurAlpha, partsFboTex, partsFbo, partsTFX, partsTFY, airPV, airVY, airVX; GLuint fireProg, airProg_Pressure, airProg_Velocity, airProg_Cracker, lensProg; #endif /* int emp_decor = 0; int sandcolour_r = 0; int sandcolour_g = 0; int sandcolour_b = 0; int sandcolour_frame = 0; unsigned char fire_r[YRES/CELL][XRES/CELL]; unsigned char fire_g[YRES/CELL][XRES/CELL]; unsigned char fire_b[YRES/CELL][XRES/CELL]; unsigned int fire_alpha[CELL*3][CELL*3]; pixel *pers_bg; char * flm_data; int flm_data_points = 4; pixel flm_data_colours[] = {PIXPACK(0xAF9F0F), PIXPACK(0xDFBF6F), PIXPACK(0x60300F), PIXPACK(0x000000)}; float flm_data_pos[] = {1.0f, 0.9f, 0.5f, 0.0f}; char * plasma_data; int plasma_data_points = 5; pixel plasma_data_colours[] = {PIXPACK(0xAFFFFF), PIXPACK(0xAFFFFF), PIXPACK(0x301060), PIXPACK(0x301040), PIXPACK(0x000000)}; float plasma_data_pos[] = {1.0f, 0.9f, 0.5f, 0.25, 0.0f};*/ char * Graphics::GenerateGradient(pixel * colours, float * points, int pointcount, int size) { int cp, i, j; pixel ptemp; char * newdata = (char*)malloc(size * 3); float poss, pose, temp; memset(newdata, 0, size*3); //Sort the Colours and Points for (i = (pointcount - 1); i > 0; i--) { for (j = 1; j <= i; j++) { if (points[j-1] > points[j]) { temp = points[j-1]; points[j-1] = points[j]; points[j] = temp; ptemp = colours[j-1]; colours[j-1] = colours[j]; colours[j] = ptemp; } } } i = 0; j = 1; poss = points[i]; pose = points[j]; for (cp = 0; cp < size; cp++) { float cpos = (float)cp / (float)size, ccpos, cccpos; if(cpos > pose && j+1 < pointcount) { poss = points[++i]; pose = points[++j]; } ccpos = cpos - poss; cccpos = ccpos / (pose - poss); if(cccpos > 1.0f) cccpos = 1.0f; newdata[(cp*3)] = PIXR(colours[i])*(1.0f-cccpos) + PIXR(colours[j])*(cccpos); newdata[(cp*3)+1] = PIXG(colours[i])*(1.0f-cccpos) + PIXG(colours[j])*(cccpos); newdata[(cp*3)+2] = PIXB(colours[i])*(1.0f-cccpos) + PIXB(colours[j])*(cccpos); } return newdata; } void *Graphics::ptif_pack(pixel *src, int w, int h, int *result_size){ int i = 0, datalen = (w*h)*3, cx = 0, cy = 0; unsigned char *red_chan = (unsigned char*)calloc(1, w*h); unsigned char *green_chan = (unsigned char*)calloc(1, w*h); unsigned char *blue_chan = (unsigned char*)calloc(1, w*h); unsigned char *data = (unsigned char*)malloc(((w*h)*3)+8); unsigned char *result = (unsigned char*)malloc(((w*h)*3)+8); for(cx = 0; cx>8; result[6] = h; result[7] = h>>8; i -= 8; if(BZ2_bzBuffToBuffCompress((char *)(result+8), (unsigned *)&i, (char *)data, datalen, 9, 0, 0) != 0){ free(data); free(result); return NULL; } *result_size = i+8; free(data); return result; } pixel *Graphics::ptif_unpack(void *datain, int size, int *w, int *h){ int width, height, i, cx, cy, resCode; unsigned char *red_chan; unsigned char *green_chan; unsigned char *blue_chan; unsigned char *data = (unsigned char*)datain; unsigned char *undata; pixel *result; if(size<16){ printf("Image empty\n"); return NULL; } if(!(data[0]=='P' && data[1]=='T' && data[2]=='i')){ printf("Image header invalid\n"); return NULL; } width = data[4]|(data[5]<<8); height = data[6]|(data[7]<<8); i = (width*height)*3; undata = (unsigned char*)calloc(1, (width*height)*3); red_chan = (unsigned char*)calloc(1, width*height); green_chan = (unsigned char*)calloc(1, width*height); blue_chan = (unsigned char *)calloc(1, width*height); result = (pixel *)calloc(width*height, PIXELSIZE); resCode = BZ2_bzBuffToBuffDecompress((char *)undata, (unsigned *)&i, (char *)(data+8), size-8, 0, 0); if (resCode){ printf("Decompression failure, %d\n", resCode); free(red_chan); free(green_chan); free(blue_chan); free(undata); free(result); return NULL; } if(i != (width*height)*3){ printf("Result buffer size mismatch, %d != %d\n", i, (width*height)*3); free(red_chan); free(green_chan); free(blue_chan); free(undata); free(result); return NULL; } memcpy(red_chan, undata, width*height); memcpy(green_chan, undata+(width*height), width*height); memcpy(blue_chan, undata+((width*height)*2), width*height); for(cx = 0; cx sw && rh > sh){ float fx, fy, fyc, fxc; double intp; pixel tr, tl, br, bl; q = (pixel *)malloc(rw*rh*PIXELSIZE); //Bilinear interpolation for upscaling for (y=0; y=sw) fxceil = sw-1; if (fyceil>=sh) fyceil = sh-1; tr = src[sw*(int)floor(fy)+fxceil]; tl = src[sw*(int)floor(fy)+(int)floor(fx)]; br = src[sw*fyceil+fxceil]; bl = src[sw*fyceil+(int)floor(fx)]; q[rw*y+x] = PIXRGB( (int)(((((float)PIXR(tl))*(1.0f-fxc))+(((float)PIXR(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXR(bl))*(1.0f-fxc))+(((float)PIXR(br))*(fxc)))*(fyc)), (int)(((((float)PIXG(tl))*(1.0f-fxc))+(((float)PIXG(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXG(bl))*(1.0f-fxc))+(((float)PIXG(br))*(fxc)))*(fyc)), (int)(((((float)PIXB(tl))*(1.0f-fxc))+(((float)PIXB(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXB(bl))*(1.0f-fxc))+(((float)PIXB(br))*(fxc)))*(fyc)) ); } } else { //Stairstepping float fx, fy, fyc, fxc; double intp; pixel tr, tl, br, bl; int rrw = rw, rrh = rh; pixel * oq; oq = (pixel *)malloc(sw*sh*PIXELSIZE); memcpy(oq, src, sw*sh*PIXELSIZE); rw = sw; rh = sh; while(rrw != rw && rrh != rh){ rw *= 0.7; rh *= 0.7; if(rw <= rrw || rh <= rrh){ rw = rrw; rh = rrh; } q = (pixel *)malloc(rw*rh*PIXELSIZE); //Bilinear interpolation for upscaling for (y=0; y=sw) fxceil = sw-1; if (fyceil>=sh) fyceil = sh-1; tr = oq[sw*(int)floor(fy)+fxceil]; tl = oq[sw*(int)floor(fy)+(int)floor(fx)]; br = oq[sw*fyceil+fxceil]; bl = oq[sw*fyceil+(int)floor(fx)]; q[rw*y+x] = PIXRGB( (int)(((((float)PIXR(tl))*(1.0f-fxc))+(((float)PIXR(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXR(bl))*(1.0f-fxc))+(((float)PIXR(br))*(fxc)))*(fyc)), (int)(((((float)PIXG(tl))*(1.0f-fxc))+(((float)PIXG(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXG(bl))*(1.0f-fxc))+(((float)PIXG(br))*(fxc)))*(fyc)), (int)(((((float)PIXB(tl))*(1.0f-fxc))+(((float)PIXB(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXB(bl))*(1.0f-fxc))+(((float)PIXB(br))*(fxc)))*(fyc)) ); } free(oq); oq = q; sw = rw; sh = rh; } } return q; } pixel *Graphics::rescale_img(pixel *src, int sw, int sh, int *qw, int *qh, int f) { int i,j,x,y,w,h,r,g,b,c; pixel p, *q; w = (sw+f-1)/f; h = (sh+f-1)/f; q = (pixel *)malloc(w*h*PIXELSIZE); for (y=0; y1) { r = (r+c/2)/c; g = (g+c/2)/c; b = (b+c/2)/c; } q[y*w+x] = PIXRGB(r, g, b); } *qw = w; *qh = h; return q; } #ifdef OGLR void clearScreen(float alpha) { if(alpha > 0.999f) { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo); glClear(GL_COLOR_BUFFER_BIT); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } else { glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); glColor4f(1.0f, 1.0f, 1.0f, alpha); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo); glBegin(GL_QUADS); glVertex2f(0, 0); glVertex2f(XRES, 0); glVertex2f(XRES, YRES); glVertex2f(0, YRES); glEnd(); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBlendEquation(GL_FUNC_ADD); } glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); } void clearScreenNP(float alpha) { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); } void ogl_blit(int x, int y, int w, int h, pixel *src, int pitch, int scale) { //glDrawPixels(w,h,GL_BGRA,GL_UNSIGNED_BYTE,src); //Why does this still think it's ABGR? glEnable( GL_TEXTURE_2D ); glBindTexture(GL_TEXTURE_2D, vidBuf); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, XRES+BARSIZE, YRES+MENUSIZE, GL_BGRA, GL_UNSIGNED_BYTE, src); glBegin(GL_QUADS); glTexCoord2d(1, 0); glVertex3f((XRES+BARSIZE)*sdl_scale, (YRES+MENUSIZE)*sdl_scale, 1.0); glTexCoord2d(0, 0); glVertex3f(0, (YRES+MENUSIZE)*sdl_scale, 1.0); glTexCoord2d(0, 1); glVertex3f(0, 0, 1.0); glTexCoord2d(1, 1); glVertex3f((XRES+BARSIZE)*sdl_scale, 0, 1.0); glEnd(); glDisable( GL_TEXTURE_2D ); glFlush(); SDL_GL_SwapBuffers (); } #endif //an easy way to draw a blob void Graphics::drawblob(int x, int y, unsigned char cr, unsigned char cg, unsigned char cb) { blendpixel(x+1, y, cr, cg, cb, 112); blendpixel(x-1, y, cr, cg, cb, 112); blendpixel(x, y+1, cr, cg, cb, 112); blendpixel(x, y-1, cr, cg, cb, 112); blendpixel(x+1, y-1, cr, cg, cb, 64); blendpixel(x-1, y-1, cr, cg, cb, 64); blendpixel(x+1, y+1, cr, cg, cb, 64); blendpixel(x-1, y+1, cr, cg, cb, 64); } //draws walls and elements for menu /*int draw_tool_xy(pixel *vid_buf, int x, int y, int b, unsigned pc) { int i, j, c; pixel gc; if (x > XRES-26 || x < 0) return 26; if ((b&0xFF) == PT_LIFE) { for (j=1; j<15; j++) { for (i=1; i<27; i++) { vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; } } c = PIXB(pc) + 3*PIXG(pc) + 2*PIXR(pc); if (c<544) { c = 255; } else { c = 0; } drawtext(vid_buf, x+14-textwidth((char *)gmenu[(b>>8)&0xFF].name)/2, y+4, (char *)gmenu[(b>>8)&0xFF].name, c, c, c, 255); } else if (b>=UI_WALLSTART) { int ds = 0; if (b-UI_WALLSTART>=0 && b-UI_WALLSTART>1)); i<27; i+=2) vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; } else if (ds==2) { for (j=1; j<15; j+=2) for (i=1; i<27; i+=2) vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; } else if (ds==3) { for (j=1; j<15; j++) for (i=1; i<27; i++) vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; } else if (ds==4) { for (j=1; j<15; j++) for (i=1; i<27; i++) if(i%CELL == j%CELL) vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; else if (i%CELL == (j%CELL)+1 || (i%CELL == 0 && j%CELL == CELL-1)) vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = gc; else vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = PIXPACK(0x202020); } else switch (b) { case WL_WALLELEC+100: for (j=1; j<15; j++) { for (i=1; i<27; i++) { if (!(i%2) && !(j%2)) { vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; } else { vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = PIXPACK(0x808080); } } } break; case WL_EWALL+100: for (j=1; j<15; j++) { for (i=1; i<6+j; i++) { if (!(i&j&1)) { vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; } } for (; i<27; i++) { if (i&j&1) { vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; } } } break; case WL_STREAM+100: for (j=1; j<15; j++) { for (i=1; i<27; i++) { vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = i==1||i==26||j==1||j==14 ? PIXPACK(0xA0A0A0) : PIXPACK(0x000000); drawtext(vid_buf, x+4, y+3, "\x8D", 255, 255, 255, 255); } } for (i=9; i<27; i++) { drawpixel(vid_buf, x+i, y+8+(int)(3.9f*cos(i*0.3f)), 255, 255, 255, 255); } break; case WL_SIGN+100: for (j=1; j<15; j++) { for (i=1; i<27; i++) { vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = i==1||i==26||j==1||j==14 ? PIXPACK(0xA0A0A0) : PIXPACK(0x000000); } } drawtext(vid_buf, x+9, y+3, "\xA1", 32, 64, 128, 255); drawtext(vid_buf, x+9, y+3, "\xA0", 255, 255, 255, 255); break; case WL_ERASE+100: for (j=1; j<15; j+=2) { for (i=1+(1&(j>>1)); i<13; i+=2) { vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; } } for (j=1; j<15; j++) { for (i=14; i<27; i++) { vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; } } break; case SPC_AIR: case SPC_HEAT: case SPC_COOL: case SPC_VACUUM: case SPC_WIND: case SPC_PGRV: case SPC_NGRV: case SPC_PROP: for (j=1; j<15; j++) for (i=1; i<27; i++) vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; c = PIXR(pc) + 3*PIXG(pc) + 2*PIXB(pc); if (c<544) { c = 255; } else { c = 0; } if (b==SPC_AIR) drawtext(vid_buf, x+14-textwidth("AIR")/2, y+4, "AIR", c, c, c, 255); else if (b==SPC_HEAT) drawtext(vid_buf, x+14-textwidth("HEAT")/2, y+4, "HEAT", c, c, c, 255); else if (b==SPC_COOL) drawtext(vid_buf, x+14-textwidth("COOL")/2, y+4, "COOL", c, c, c, 255); else if (b==SPC_VACUUM) drawtext(vid_buf, x+14-textwidth("VAC")/2, y+4, "VAC", c, c, c, 255); else if (b==SPC_WIND) drawtext(vid_buf, x+14-textwidth("WIND")/2, y+4, "WIND", c, c, c, 255); else if (b==SPC_PGRV) drawtext(vid_buf, x+14-textwidth("PGRV")/2, y+4, "PGRV", c, c, c, 255); else if (b==SPC_NGRV) drawtext(vid_buf, x+14-textwidth("NGRV")/2, y+4, "NGRV", c, c, c, 255); else if (b==SPC_PROP) drawtext(vid_buf, x+14-textwidth("PROP")/2, y+4, "PROP", c, c, c, 255); break; default: for (j=1; j<15; j++) for (i=1; i<27; i++) vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; } if (b==WL_ERASE+100) { for (j=4; j<12; j++) { vid_buf[(XRES+BARSIZE)*(y+j)+(x+j+6)] = PIXPACK(0xFF0000); vid_buf[(XRES+BARSIZE)*(y+j)+(x+j+7)] = PIXPACK(0xFF0000); vid_buf[(XRES+BARSIZE)*(y+j)+(x-j+21)] = PIXPACK(0xFF0000); vid_buf[(XRES+BARSIZE)*(y+j)+(x-j+22)] = PIXPACK(0xFF0000); } } } else { //x = 2+32*(b/2); //y = YRES+2+20*(b%2); for (j=1; j<15; j++) { for (i=1; i<27; i++) { vid_buf[(XRES+BARSIZE)*(y+j)+(x+i)] = pc; } } if (b==0) { for (j=4; j<12; j++) { vid_buf[(XRES+BARSIZE)*(y+j)+(x+j+6)] = PIXPACK(0xFF0000); vid_buf[(XRES+BARSIZE)*(y+j)+(x+j+7)] = PIXPACK(0xFF0000); vid_buf[(XRES+BARSIZE)*(y+j)+(x-j+21)] = PIXPACK(0xFF0000); vid_buf[(XRES+BARSIZE)*(y+j)+(x-j+22)] = PIXPACK(0xFF0000); } } c = PIXB(ptypes[b].pcolors) + 3*PIXG(ptypes[b].pcolors) + 2*PIXR(ptypes[b].pcolors); if (c<544) { c = 255; } else { c = 0; } drawtext(vid_buf, x+14-textwidth((char *)ptypes[b].name)/2, y+4, (char *)ptypes[b].name, c, c, c, 255); } return 26; }*/ /*void draw_menu(pixel *vid_buf, int i, int hover) { if (i==SEC&&SEC!=0) drawrect(vid_buf, (XRES+BARSIZE)-16, (i*16)+YRES+MENUSIZE-16-(SC_TOTAL*16), 14, 14, 0, 255, 255, 255); else drawrect(vid_buf, (XRES+BARSIZE)-16, (i*16)+YRES+MENUSIZE-16-(SC_TOTAL*16), 14, 14, 255, 255, 255, 255); if (hover==i) { fillrect(vid_buf, (XRES+BARSIZE)-16, (i*16)+YRES+MENUSIZE-16-(SC_TOTAL*16), 14, 14, 255, 255, 255, 255); drawtext(vid_buf, (XRES+BARSIZE)-13, (i*16)+YRES+MENUSIZE-14-(SC_TOTAL*16), msections[i].icon, 0, 0, 0, 255); } else { drawtext(vid_buf, (XRES+BARSIZE)-13, (i*16)+YRES+MENUSIZE-14-(SC_TOTAL*16), msections[i].icon, 255, 255, 255, 255); } }*/ /*void draw_color_menu(pixel *vid_buf, int i, int hover) { drawrect(vid_buf, (XRES+BARSIZE)-16, (i*16)+YRES+MENUSIZE-16-(DECO_SECTIONS*16), 14, 14, 255, 255, 255, 255); if (hover==i) { fillrect(vid_buf, (XRES+BARSIZE)-16, (i*16)+YRES+MENUSIZE-16-(DECO_SECTIONS*16), 14, 14, 255, 255, 255, 255); drawtext(vid_buf, (XRES+BARSIZE)-13, (i*16)+YRES+MENUSIZE-14-(DECO_SECTIONS*16), colorsections[i].icon, 0, 0, 0, 255); } else { drawtext(vid_buf, (XRES+BARSIZE)-13, (i*16)+YRES+MENUSIZE-14-(DECO_SECTIONS*16), colorsections[i].icon, 255, 255, 255, 255); } }*/ //draws a pixel, identical to blendpixel(), except blendpixel has OpenGL support TPT_INLINE void Graphics::drawpixel(int x, int y, int r, int g, int b, int a) { #ifdef PIXALPHA pixel t; if (x<0 || y<0 || x>=XRES+BARSIZE || y>=YRES+MENUSIZE) return; if (a!=255) { t = vid[y*(XRES+BARSIZE)+x]; r = (a*r + (255-a)*PIXR(t)) >> 8; g = (a*g + (255-a)*PIXG(t)) >> 8; b = (a*b + (255-a)*PIXB(t)) >> 8; a = a > PIXA(t) ? a : PIXA(t); } vid[y*(XRES+BARSIZE)+x] = PIXRGBA(r,g,b,a); #else pixel t; if (x<0 || y<0 || x>=XRES+BARSIZE || y>=YRES+MENUSIZE) return; if (a!=255) { t = vid[y*(XRES+BARSIZE)+x]; r = (a*r + (255-a)*PIXR(t)) >> 8; g = (a*g + (255-a)*PIXG(t)) >> 8; b = (a*b + (255-a)*PIXB(t)) >> 8; } vid[y*(XRES+BARSIZE)+x] = PIXRGB(r,g,b); #endif } inline int Graphics::drawchar(int x, int y, int c, int r, int g, int b, int a) { int i, j, w, bn = 0, ba = 0; char *rp = font_data + font_ptrs[c]; w = *(rp++); for (j=0; j>= 2; bn -= 2; } return x + w; } inline int Graphics::addchar(int x, int y, int c, int r, int g, int b, int a) { int i, j, w, bn = 0, ba = 0; char *rp = font_data + font_ptrs[c]; w = *(rp++); for (j=0; j>= 2; bn -= 2; } return x + w; } int Graphics::drawtext(int x, int y, std::string &s, int r, int g, int b, int a) { return drawtext(x, y, s.c_str(), r, g, b, a); } int Graphics::drawtext(int x, int y, const char *s, int r, int g, int b, int a) { int sx = x; for (; *s; s++) { if (*s == '\n') { x = sx; y += FONT_H+2; } else if (*s == '\b') { switch (s[1]) { case 'w': r = g = b = 255; break; case 'g': r = g = b = 192; break; case 'o': r = 255; g = 216; b = 32; break; case 'r': r = 255; g = b = 0; break; case 'l': r = 255; g = b = 75; break; case 'b': r = g = 0; b = 255; break; case 't': b = 255; g = 170; r = 32; break; } s++; } else x = drawchar(x, y, *(unsigned char *)s, r, g, b, a); } return x; } //Draw text with an outline int Graphics::drawtext_outline(int x, int y, const char *s, int r, int g, int b, int a, int olr, int olg, int olb, int ola) { drawtext(x-1, y-1, s, olr, olg, olb, ola); drawtext(x+1, y+1, s, olr, olg, olb, ola); drawtext(x-1, y+1, s, olr, olg, olb, ola); drawtext(x+1, y-1, s, olr, olg, olb, ola); return drawtext(x, y, s, r, g, b, a); } int Graphics::drawtextwrap(int x, int y, int w, const char *s, int r, int g, int b, int a) { int sx = x; int rh = 12; int rw = 0; int cw = x; int wordlen; int charspace; while (*s) { wordlen = strcspn(s," .,!?\n"); charspace = textwidthx((char *)s, w-(x-cw)); if (charspace=-1; s++) { if (*s == '\n') { x = sx; rw = 0; y += FONT_H+2; } else if (*s == '\b') { switch (s[1]) { case 'w': r = g = b = 255; break; case 'g': r = g = b = 192; break; case 'o': r = 255; g = 216; b = 32; break; case 'r': r = 255; g = b = 0; break; case 'l': r = 255; g = b = 75; break; case 'b': r = g = 0; b = 255; break; case 't': b = 255; g = 170; r = 32; break; } s++; } else { if (x-cw>=w) { x = sx; rw = 0; y+=FONT_H+2; rh+=FONT_H+2; } x = drawchar(x, y, *(unsigned char *)s, r, g, b, a); } } } return rh; } //draws a rectange, (x,y) are the top left coords. void Graphics::drawrect(int x, int y, int w, int h, int r, int g, int b, int a) { int i; for (i=0; i<=w; i++) { drawpixel(x+i, y, r, g, b, a); drawpixel(x+i, y+h, r, g, b, a); } for (i=1; i=w && x+textwidth(s)>=w+5) break; x = drawchar(x, y, *(unsigned char *)s, r, g, b, a); } if (*s) for (i=0; i<3; i++) x = drawchar(x, y, '.', r, g, b, a); return x; } int Graphics::textnwidth(char *s, int n) { int x = 0; for (; *s; s++) { if (!n) break; if(((char)*s)=='\b') { s++; continue; } x += font_data[font_ptrs[(int)(*(unsigned char *)s)]]; n--; } return x-1; } void Graphics::textnpos(char *s, int n, int w, int *cx, int *cy) { int x = 0; int y = 0; int wordlen, charspace; while (*s&&n) { wordlen = strcspn(s," .,!?\n"); charspace = textwidthx(s, w-x); if (charspace=-1; s++) { if (!n) { break; } x += font_data[font_ptrs[(int)(*(unsigned char *)s)]]; if (x>=w) { x = 0; y += FONT_H+2; } n--; } } *cx = x-1; *cy = y; } int Graphics::textwidthx(char *s, int w) { int x=0,n=0,cw; for (; *s; s++) { if((char)*s == '\b') { s++; continue; } cw = font_data[font_ptrs[(int)(*(unsigned char *)s)]]; if (x+(cw/2) >= w) break; x += cw; n++; } return n; } int Graphics::textposxy(char *s, int width, int w, int h) { int x=0,y=0,n=0,cw, wordlen, charspace; while (*s) { wordlen = strcspn(s," .,!?\n"); charspace = textwidthx(s, width-x); if (charspace=-1; s++) { cw = font_data[font_ptrs[(int)(*(unsigned char *)s)]]; if ((x+(cw/2) >= w && y+6 >= h)||(y+6 >= h+FONT_H+2)) return n++; x += cw; if (x>=width) { x = 0; y += FONT_H+2; } n++; } } return n; } int Graphics::textwrapheight(char *s, int width) { int x=0, height=FONT_H+2, cw; int wordlen; int charspace; while (*s) { wordlen = strcspn(s," .,!?\n"); charspace = textwidthx(s, width-x); if (charspace=-1; s++) { if (*s == '\n') { x = 0; height += FONT_H+2; } else if (*s == '\b') { s++; } else { cw = font_data[font_ptrs[(int)(*(unsigned char *)s)]]; if (x+cw>=width) { x = 0; height += FONT_H+2; } x += cw; } } } return height; } //the most used function for drawing a pixel, because it has OpenGL support, which is not fully implemented. TPT_INLINE void Graphics::blendpixel(int x, int y, int r, int g, int b, int a) { #ifdef PIXALPHA pixel t; if (x<0 || y<0 || x>=XRES+BARSIZE || y>=YRES+MENUSIZE) return; if (a!=255) { t = vid[y*(XRES+BARSIZE)+x]; r = (a*r + (255-a)*PIXR(t)) >> 8; g = (a*g + (255-a)*PIXG(t)) >> 8; b = (a*b + (255-a)*PIXB(t)) >> 8; a = a > PIXA(t) ? a : PIXA(t); } vid[y*(XRES+BARSIZE)+x] = PIXRGBA(r,g,b,a); #else pixel t; if (x<0 || y<0 || x>=XRES+BARSIZE || y>=YRES+MENUSIZE) return; if (a!=255) { t = vid[y*(XRES+BARSIZE)+x]; r = (a*r + (255-a)*PIXR(t)) >> 8; g = (a*g + (255-a)*PIXG(t)) >> 8; b = (a*b + (255-a)*PIXB(t)) >> 8; } vid[y*(XRES+BARSIZE)+x] = PIXRGB(r,g,b); #endif } void Graphics::draw_icon(int x, int y, Icon icon) { switch(icon) { case IconOpen: drawchar(x, y, 0x81, 255, 255, 255, 255); break; case IconReload: drawchar(x, y, 0x91, 255, 255, 255, 255); break; case IconSave: drawchar(x, y, 0x82, 255, 255, 255, 255); break; case IconVoteUp: drawchar(x, y, 0xCB, 0, 187, 18, 255); break; case IconVoteDown: drawchar(x, y, 0xCA, 187, 40, 0, 255); break; case IconTag: drawchar(x, y, 0x83, 255, 255, 255, 255); break; case IconNew: drawchar(x, y, 0x92, 255, 255, 255, 255); break; case IconLogin: drawchar(x, y, 0x84, 255, 255, 255, 255); break; case IconSimulationSettings: drawchar(x, y, 0xCF, 255, 255, 255, 255); break; case IconRenderSettings: addchar(x, y, 0xD8, 255, 0, 0, 255); addchar(x, y, 0xD9, 0, 255, 0, 255); addchar(x, y, 0xDA, 0, 0, 255, 255); break; case IconPause: drawchar(x, y, 0x90, 255, 255, 255, 255); break; case IconReport: drawchar(x, y, 0xE3, 255, 255, 0, 255); break; case IconFavourite: drawchar(x, y, 0xCC, 192, 160, 64, 255); break; case IconVoteSort: case IconDateSort: case IconFolder: case IconSearch: case IconDelete: default: drawchar(x, y, 't', 255, 255, 255, 255); break; } } void Graphics::draw_line(int x1, int y1, int x2, int y2, int r, int g, int b, int a) //Draws a line { int dx, dy, i, sx, sy, check, e, x, y; dx = abs(x1-x2); dy = abs(y1-y2); sx = isign(x2-x1); sy = isign(y2-y1); x = x1; y = y1; check = 0; if (dy>dx) { dx = dx+dy; dy = dx-dy; dx = dx-dy; check = 1; } e = (dy<<2)-dx; for (i=0; i<=dx; i++) { if (x>=0 && y>=0 && x=0) { if (check==1) x = x+sx; else y = y+sy; e = e-(dx<<2); } if (check==1) y = y+sy; else x = x+sx; e = e+(dy<<2); } } //adds color to a pixel, does not overwrite. void Graphics::addpixel(int x, int y, int r, int g, int b, int a) { pixel t; if (x<0 || y<0 || x>=XRES+BARSIZE || y>=YRES+MENUSIZE) return; t = vid[y*(XRES+BARSIZE)+x]; r = (a*r + 255*PIXR(t)) >> 8; g = (a*g + 255*PIXG(t)) >> 8; b = (a*b + 255*PIXB(t)) >> 8; if (r>255) r = 255; if (g>255) g = 255; if (b>255) b = 255; vid[y*(XRES+BARSIZE)+x] = PIXRGB(r,g,b); } //draws one of two colors, so that it is always clearly visible void Graphics::xor_pixel(int x, int y) { int c; if (x<0 || y<0 || x>=XRES || y>=YRES) return; c = vid[y*(XRES+BARSIZE)+x]; c = PIXB(c) + 3*PIXG(c) + 2*PIXR(c); if (c<512) vid[y*(XRES+BARSIZE)+x] = PIXPACK(0xC0C0C0); else vid[y*(XRES+BARSIZE)+x] = PIXPACK(0x404040); } //same as xor_pixel, but draws a line of it void Graphics::xor_line(int x1, int y1, int x2, int y2) { int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy; float e, de; if (cp) { y = x1; x1 = y1; y1 = y; y = x2; x2 = y2; y2 = y; } if (x1 > x2) { y = x1; x1 = x2; x2 = y; y = y1; y1 = y2; y2 = y; } dx = x2 - x1; dy = abs(y2 - y1); e = 0.0f; if (dx) de = dy/(float)dx; else de = 0.0f; y = y1; sy = (y1= 0.5f) { y += sy; e -= 1.0f; } } } //same as blend_pixel, but draws a line of it void Graphics::blend_line(int x1, int y1, int x2, int y2, int r, int g, int b, int a) { int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy; float e, de; if (cp) { y = x1; x1 = y1; y1 = y; y = x2; x2 = y2; y2 = y; } if (x1 > x2) { y = x1; x1 = x2; x2 = y; y = y1; y1 = y2; y2 = y; } dx = x2 - x1; dy = abs(y2 - y1); e = 0.0f; if (dx) de = dy/(float)dx; else de = 0.0f; y = y1; sy = (y1= 0.5f) { y += sy; e -= 1.0f; } } } //same as xor_pixel, but draws a rectangle void Graphics::xor_rect(int x, int y, int w, int h) { int i; for (i=0; i>i)&1) { // Need a spread of wavelengths to get a smooth spectrum, 5 bits seems to work reasonably well if (i>2) tmp = 0x1F << (i-2); else tmp = 0x1F >> (2-i); cg = 0; cb = 0; cr = 0; for (j=0; j<12; j++) { cr += (tmp >> (j+18)) & 1; cb += (tmp >> j) & 1; } for (j=0; j<13; j++) cg += (tmp >> (j+9)) & 1; tmp = 624/(cr+cg+cb+1); cr *= tmp; cg *= tmp; cb *= tmp; for (j=0; j255?255:cr,cg>255?255:cg,cb>255?255:cb,255); } } } pixel *Graphics::render_packed_rgb(void *image, int width, int height, int cmp_size) { unsigned char *tmp; pixel *res; int i; tmp = (unsigned char *)malloc(width*height*3); if (!tmp) return NULL; res = (pixel *)malloc(width*height*PIXELSIZE); if (!res) { free(tmp); return NULL; } i = width*height*3; if (BZ2_bzBuffToBuffDecompress((char *)tmp, (unsigned *)&i, (char *)image, cmp_size, 0, 0)) { free(res); free(tmp); return NULL; } for (i=0; i YRES+MENUSIZE) h = (YRES+MENUSIZE)-y; //Adjust height to prevent drawing off the bottom if(a >= 255) for (j=0; j0) r--; if (g>0) g--; if (b>0) b--; dst[i] = PIXRGB(r,g,b); } } void Graphics::dim_copy_pers(pixel *dst, pixel *src) //for persistent view, reduces rgb slowly { int i,r,g,b; for (i=0; i<(XRES+BARSIZE)*YRES; i++) { r = PIXR(src[i]); g = PIXG(src[i]); b = PIXB(src[i]); if (r>0) r--; if (g>0) g--; if (b>0) b--; dst[i] = PIXRGB(r,g,b); } } /*void render_zoom(pixel *img) //draws the zoom box { #ifdef OGLR int origBlendSrc, origBlendDst; float zcx1, zcx0, zcy1, zcy0, yfactor, xfactor, i; //X-Factor is shit, btw xfactor = 1.0f/(float)XRES; yfactor = 1.0f/(float)YRES; zcx0 = (zoom_x)*xfactor; zcx1 = (zoom_x+ZSIZE)*xfactor; zcy0 = (zoom_y)*yfactor; zcy1 = ((zoom_y+ZSIZE))*yfactor; glGetIntegerv(GL_BLEND_SRC, &origBlendSrc); glGetIntegerv(GL_BLEND_DST, &origBlendDst); glBlendFunc(GL_ONE, GL_ZERO); glEnable( GL_TEXTURE_2D ); //glReadBuffer(GL_AUX0); glBindTexture(GL_TEXTURE_2D, partsFboTex); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBegin(GL_QUADS); glTexCoord2d(zcx1, zcy1); glVertex3f((zoom_wx+ZSIZE*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR))*sdl_scale, 1.0); glTexCoord2d(zcx0, zcy1); glVertex3f(zoom_wx*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR))*sdl_scale, 1.0); glTexCoord2d(zcx0, zcy0); glVertex3f(zoom_wx*sdl_scale, (YRES+MENUSIZE-zoom_wy)*sdl_scale, 1.0); glTexCoord2d(zcx1, zcy0); glVertex3f((zoom_wx+ZSIZE*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-zoom_wy)*sdl_scale, 1.0); glEnd(); glBindTexture(GL_TEXTURE_2D, 0); glDisable( GL_TEXTURE_2D ); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glLineWidth(sdl_scale); glEnable(GL_LINE_SMOOTH); glBegin(GL_LINES); glColor4f(0.0f, 0.0f, 0.0f, 1.0f); for(i = 0; i < ZSIZE; i++) { glVertex2f((zoom_wx+ZSIZE*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR)+i*ZFACTOR)*sdl_scale); glVertex2f(zoom_wx*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR)+i*ZFACTOR)*sdl_scale); glVertex2f((zoom_wx+i*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR))*sdl_scale); glVertex2f((zoom_wx+i*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-zoom_wy)*sdl_scale); } glEnd(); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBegin(GL_LINE_STRIP); glVertex3i((zoom_wx-1)*sdl_scale, (YRES+MENUSIZE-zoom_wy)*sdl_scale, 0); glVertex3i((zoom_wx-1)*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR))*sdl_scale, 0); glVertex3i((zoom_wx+ZSIZE*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-(zoom_wy+ZSIZE*ZFACTOR))*sdl_scale, 0); glVertex3i((zoom_wx+ZSIZE*ZFACTOR)*sdl_scale, (YRES+MENUSIZE-zoom_wy)*sdl_scale, 0); glVertex3i((zoom_wx-1)*sdl_scale, (YRES+MENUSIZE-zoom_wy)*sdl_scale, 0); glEnd(); glDisable(GL_LINE_SMOOTH); glDisable(GL_LINE_SMOOTH); if(zoom_en) { glEnable(GL_COLOR_LOGIC_OP); //glEnable(GL_LINE_SMOOTH); glLogicOp(GL_XOR); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBegin(GL_LINE_STRIP); glVertex3i((zoom_x-1)*sdl_scale, (YRES+MENUSIZE-(zoom_y-1))*sdl_scale, 0); glVertex3i((zoom_x-1)*sdl_scale, (YRES+MENUSIZE-(zoom_y+ZSIZE))*sdl_scale, 0); glVertex3i((zoom_x+ZSIZE)*sdl_scale, (YRES+MENUSIZE-(zoom_y+ZSIZE))*sdl_scale, 0); glVertex3i((zoom_x+ZSIZE)*sdl_scale, (YRES+MENUSIZE-(zoom_y-1))*sdl_scale, 0); glVertex3i((zoom_x-1)*sdl_scale, (YRES+MENUSIZE-(zoom_y-1))*sdl_scale, 0); glEnd(); glDisable(GL_COLOR_LOGIC_OP); } glLineWidth(1); glBlendFunc(origBlendSrc, origBlendDst); #else int x, y, i, j; pixel pix; drawrect(img, zoom_wx-2, zoom_wy-2, ZSIZE*ZFACTOR+2, ZSIZE*ZFACTOR+2, 192, 192, 192, 255); drawrect(img, zoom_wx-1, zoom_wy-1, ZSIZE*ZFACTOR, ZSIZE*ZFACTOR, 0, 0, 0, 255); clearrect(img, zoom_wx, zoom_wy, ZSIZE*ZFACTOR, ZSIZE*ZFACTOR); for (j=0; jPT_NUM) return 2; if (c[5]!=CELL || c[6]!=XRES/CELL || c[7]!=YRES/CELL) return 3; i = XRES*YRES; d = (unsigned char *)malloc(i); if (!d) return 1; if (BZ2_bzBuffToBuffDecompress((char *)d, (unsigned *)&i, (char *)(c+8), size-8, 0, 0)) return 1; size = i; } else d = c; if (size < XRES*YRES) { if (bzip2) free(d); return 1; } sy = 0; for (y=0; y+scl<=YRES; y+=scl) { sx = 0; for (x=0; x+scl<=XRES; x+=scl) { a = 0; r = g = b = 0; for (j=0; j=PT_NUM) goto corrupt; r += PIXR(ptypes[t].pcolors); g += PIXG(ptypes[t].pcolors); b += PIXB(ptypes[t].pcolors); a ++; } } if (a) { a = 256/a; r = (r*a)>>8; g = (g*a)>>8; b = (b*a)>>8; } drawpixel(vid_buf, px+sx, py+sy, r, g, b, 255); sx++; } sy++; } if (bzip2) free(d); return 0; corrupt: if (bzip2) free(d); return 1; }*/ //draws the cursor /*void Graphics::render_cursor(pixel *vid, int x, int y, int t, int rx, int ry) { #ifdef OGLR int i; if (trx || (j+1)>ry)) { xor_pixel(x+i, y+j, vid); xor_pixel(x-i, y-j, vid); if (i&&j)xor_pixel(x+i, y-j, vid); if (i&&j)xor_pixel(x-i, y+j, vid); } } else if (CURRENT_BRUSH==CIRCLE_BRUSH) { for (j=0; j<=ry; j++) for (i=0; i<=rx; i++) if (pow(i,2)*pow(ry,2)+pow(j,2)*pow(rx,2)<=pow(rx,2)*pow(ry,2) && (pow(i+1,2)*pow(ry,2)+pow(j,2)*pow(rx,2)>pow(rx,2)*pow(ry,2) || pow(i,2)*pow(ry,2)+pow(j+1,2)*pow(rx,2)>pow(rx,2)*pow(ry,2))) { xor_pixel(x+i, y+j, vid); if (j) xor_pixel(x+i, y-j, vid); if (i) xor_pixel(x-i, y+j, vid); if (i&&j) xor_pixel(x-i, y-j, vid); } } else if (CURRENT_BRUSH==TRI_BRUSH) { for (j=-ry; j<=ry; j++) for (i=-rx; i<=0; i++) if ((j <= ry ) && ( j >= (((-2.0*ry)/(rx))*i)-ry ) && (j+1>ry || ( j-1 < (((-2.0*ry)/(rx))*i)-ry )) ) { xor_pixel(x+i, y+j, vid); if (i) xor_pixel(x-i, y+j, vid); } } } else //wall cursor { int tc; c = (rx/CELL) * CELL; x = (x/CELL) * CELL; y = (y/CELL) * CELL; tc = !((c%(CELL*2))==0); x -= c/2; y -= c/2; x += tc*(CELL/2); y += tc*(CELL/2); for (i=0; iparts; char infobuf[256]; if(debug_flags & DEBUG_PERFORMANCE_FRAME || debug_flags & DEBUG_PERFORMANCE_CALC) { int t1, t2, x = 0, i = debug_perf_istart; float partiavg = 0, frameavg = 0; while(i != debug_perf_iend) { partiavg += abs(debug_perf_partitime[i]/100000); frameavg += abs(debug_perf_frametime[i]/100000); if(debug_flags & DEBUG_PERFORMANCE_CALC) t1 = abs(debug_perf_partitime[i]/100000); else t1 = 0; if(debug_flags & DEBUG_PERFORMANCE_FRAME) t2 = abs(debug_perf_frametime[i]/100000); else t2 = 0; if(t1 > YRES) t1 = YRES; if(t1+t2 > YRES) t2 = YRES-t1; if(t1>0) draw_line(vid, x, YRES, x, YRES-t1, 0, 255, 120, XRES+BARSIZE); if(t2>0) draw_line(vid, x, YRES-t1, x, YRES-(t1+t2), 255, 120, 0, XRES+BARSIZE); i++; x++; i %= DEBUG_PERF_FRAMECOUNT; } if(debug_flags & DEBUG_PERFORMANCE_CALC) t1 = abs(partiavg / x); else t1 = 0; if(debug_flags & DEBUG_PERFORMANCE_FRAME) t2 = abs(frameavg / x); else t2 = 0; if(t1 > YRES) t1 = YRES; if(t1+t2 > YRES) t2 = YRES-t1; if(t1>0) fillrect(vid, x, YRES-t1-1, 5, t1+2, 0, 255, 0, 255); if(t2>0) fillrect(vid, x, (YRES-t1)-t2-1, 5, t2+1, 255, 0, 0, 255); } if(debug_flags & DEBUG_DRAWTOOL) { if(lm == 1) //Line tool { blend_line(vid, 0, line_y, XRES, line_y, 255, 255, 255, 120); blend_line(vid, line_x, 0, line_x, YRES, 255, 255, 255, 120); blend_line(vid, 0, ly, XRES, ly, 255, 255, 255, 120); blend_line(vid, lx, 0, lx, YRES, 255, 255, 255, 120); sprintf(infobuf, "%d x %d", lx, ly); drawtext_outline(vid, lx+(lx>line_x?3:-textwidth(infobuf)-3), ly+(lyline_y?-10:3), infobuf, 255, 255, 255, 200, 0, 0, 0, 120); sprintf(infobuf, "%d", abs(line_x-lx)); drawtext_outline(vid, (line_x+lx)/2-textwidth(infobuf)/2, line_y+(ly>line_y?-10:3), infobuf, 255, 255, 255, 200, 0, 0, 0, 120); sprintf(infobuf, "%d", abs(line_y-ly)); drawtext_outline(vid, line_x+(lxparts_lastActiveIndex, NPART, (((float)sim->parts_lastActiveIndex)/((float)NPART))*100.0f); for(i = 0; i < NPART; i++){ if(parts[i].type){ drawpixel(vid, x, y, 255, 255, 255, 180); } else { drawpixel(vid, x, y, 0, 0, 0, 180); } if(i == sim->parts_lastActiveIndex) { lpx = x; lpy = y; } x++; if(x>=XRES){ y++; x = 0; } } draw_line(vid, 0, lpy, XRES, lpy, 0, 255, 120, XRES+BARSIZE); draw_line(vid, lpx, 0, lpx, YRES, 0, 255, 120, XRES+BARSIZE); drawpixel(vid, lpx, lpy, 255, 50, 50, 220); drawpixel(vid, lpx+1, lpy, 255, 50, 50, 120); drawpixel(vid, lpx-1, lpy, 255, 50, 50, 120); drawpixel(vid, lpx, lpy+1, 255, 50, 50, 120); drawpixel(vid, lpx, lpy-1, 255, 50, 50, 120); fillrect(vid, 7, YRES-26, textwidth(infobuf)+5, 14, 0, 0, 0, 180); drawtext(vid, 10, YRES-22, infobuf, 255, 255, 255, 255); } }*/ void Graphics::Clear() { memset(vid, 0, PIXELSIZE * ((XRES+BARSIZE) * (YRES+MENUSIZE))); } void Graphics::AttachSDLSurface(SDL_Surface * surface) { sdl_scrn = surface; } void Graphics::Blit() { if(sdl_scrn) { pixel * dst; pixel * src = vid; int j, x = 0, y = 0, w = XRES+BARSIZE, h = YRES+MENUSIZE, pitch = XRES+BARSIZE; if (SDL_MUSTLOCK(sdl_scrn)) if (SDL_LockSurface(sdl_scrn)<0) return; dst=(pixel *)sdl_scrn->pixels+y*sdl_scrn->pitch/PIXELSIZE+x; for (j=0; jpitch/PIXELSIZE; src+=pitch; } if (SDL_MUSTLOCK(sdl_scrn)) SDL_UnlockSurface(sdl_scrn); SDL_UpdateRect(sdl_scrn,0,0,0,0); } } Graphics::Graphics(): sdl_scrn(NULL) { vid = (pixel *)malloc(PIXELSIZE * ((XRES+BARSIZE) * (YRES+MENUSIZE))); } Graphics::~Graphics() { free(vid); }