/* * Abuse - dark 2D side-scrolling platform game * Copyright (c) 1995 Crack dot Com * * This software was released into the Public Domain. As with most public * domain software, no warranty is made or implied by Crack dot Com or * Jonathan Clark. */ #include "config.h" #include "timage.hpp" void trans_image::make_color(int c) { uint8_t *dp=data; int y,x; for (y=0;yscan_line(0),*dp=data,*dline; int y,x; for (y=0;ynext_line(y,d); } return im; } trans_image::trans_image(image *im, char const *name) { int size=0,x,y; uint8_t *sl,*datap,*marker; w=im->width(); h=im->height(); // first we must find out how much data to allocate for (y=0;yheight();y++) { sl=im->scan_line(y); x=0; while (xwidth(),hh=im->height(); datap=data; if (!datap) { printf("size = %d %d (%d)\n",im->width(),im->height(),size); } CONDITION(datap,"malloc error for trans_image::data"); for (y=0;yscan_line(y); x=0; while (xwidth() && (*sl)==0) { sl++; x++; (*datap)++; } datap++; if (xwidth() && (*sl)!=0) { (*marker)++; (*datap)=*sl; datap++; x++; sl++; } } } } } void trans_image::put_scan_line(image *screen, int x, int y, int line) // always transparent { int16_t x1,y1,x2,y2; screen->get_clip(x1,y1,x2,y2); if (y+liney2 || x>x2 || x+w-1scan_line(y)+x; for (ix=0;ixx2) // clipped totally on the right? return ; // we are done, return! else if (x+ix+run_length-1>x2) // partially clipped? { memcpy(screen_line,datap,(x+ix+run_length-1)-x2); // slam what we can return ; // and return 'cause we are done with the line } else { memcpy(screen_line,datap,run_length); screen_line+=run_length; datap+=run_length; ix+=run_length; } } } } } inline uint8_t *trans_image::clip_y(image *screen, int x1, int y1, int x2, int y2, int x, int &y, int &ysteps) { // check to see if it is total clipped out first if (y+h<=y1 || y>y2 || x>x2 || x+w<=x1) return NULL; register uint8_t *datap=data; ysteps=height(); if (yy2) // check to see if it gets clipped at the bottom ysteps-=(y+ysteps-y2-1); screen->add_dirty(max(x,x1),y,min(x+width()-1,x2),y+h-1); return datap; } void trans_image::put_image_filled(image *screen, int x, int y, uint8_t fill_color) { int16_t x1,y1,x2,y2; int chop_length,ysteps; screen->get_clip(x1,y1,x2,y2); register uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line; if (!datap) return ; // if clip_y says nothing to draw, return screen_line=screen->scan_line(y)+x; int sw=screen->width()-w; x1-=x; x2-=x; for (;ysteps>0;ysteps--) { register int ix,slam_length; for (ix=0;ixx2) // see if this run is totally clipped { datap+=slam_length; ix+=slam_length; screen_line+=slam_length; } else { if (ix=slam_length) // see if we chopped it all off { // yes, we did ix+=slam_length; // advance everything to the end of run screen_line+=slam_length; datap+=slam_length; slam_length=0; } else { slam_length-=chop_length; // else advance everything to begining of slam ix+=chop_length; screen_line+=chop_length; datap+=chop_length; } } if (slam_length) // see if there is anything left to slam { if (ix+slam_length>x2) // see if right side needs to be chopped off memcpy(screen_line,datap,x2-ix+1); else memcpy(screen_line,datap,slam_length); datap+=slam_length; ix+=slam_length; screen_line+=slam_length; } } } } screen_line+=sw; } } void trans_image::put_image_offseted(image *screen, uint8_t *s_off) // if screen x & y offset already calculated save a mul { int ix,ysteps=height(); int screen_skip=screen->width()-w; uint8_t skip,*datap=data; for (;ysteps;ysteps--) { for (ix=0;ixscan_line(0)) printf("bad write"); if (ix=screen->scan_line(screen->height()+1)) printf("bad write"); } } s_off+=screen_skip; } } void trans_image::put_image(image *screen, int x, int y) { int16_t x1,y1,x2,y2; int chop_length,ysteps; screen->get_clip(x1,y1,x2,y2); register uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line; if (!datap) return ; // if clip_y says nothing to draw, return screen_line=screen->scan_line(y)+x; int sw=screen->width(); x1-=x; x2-=x; for (;ysteps>0;ysteps--) { register int ix,slam_length; for (ix=0;ixx2) // see if this run is totally clipped { datap+=slam_length; ix+=slam_length; } else { if (ix=slam_length) // see if we chopped it all off { // yes, we did ix+=slam_length; // advance everything to the end of run datap+=slam_length; slam_length=0; } else { slam_length-=chop_length; // else advance everything to begining of slam ix+=chop_length; datap+=chop_length; } } if (slam_length) // see if there is anything left to slam { if (ix+slam_length>x2) // see if right side needs to be chopped off memcpy(screen_line+ix,datap,x2-ix+1); else memcpy(screen_line+ix,datap,slam_length); datap+=slam_length; ix+=slam_length; } } } } screen_line+=sw; } } void trans_image::put_remaped(image *screen, int x, int y, uint8_t *remap) { int16_t x1,y1,x2,y2; int chop_length,ysteps; screen->get_clip(x1,y1,x2,y2); register uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line; if (!datap) return ; // if clip_y says nothing to draw, return screen_line=screen->scan_line(y)+x; int sw=screen->width(); x1-=x; x2-=x; for (;ysteps>0;ysteps--) { register int ix,slam_length; for (ix=0;ixx2) // see if this run is totally clipped { datap+=slam_length; ix+=slam_length; } else { if (ix=slam_length) // see if we chopped it all off { // yes, we did ix+=slam_length; // advance everything to the end of run datap+=slam_length; slam_length=0; } else { slam_length-=chop_length; // else advance everything to begining of slam ix+=chop_length; datap+=chop_length; } } if (slam_length) // see if there is anything left to slam { register int counter; if (ix+slam_length>x2) // see if right side needs to be chopped off counter=x2-ix+1; else counter=slam_length; register uint8_t *sl=screen_line+ix,*sl2=datap; ix+=slam_length; datap+=slam_length; while (counter) { counter--; *(sl)=remap[*(sl2)]; sl++; sl2++; } } } } } screen_line+=sw; } } void trans_image::put_double_remaped(image *screen, int x, int y, uint8_t *remap, uint8_t *remap2) { int16_t x1,y1,x2,y2; int chop_length,ysteps; screen->get_clip(x1,y1,x2,y2); register uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line; if (!datap) return ; // if clip_y says nothing to draw, return screen_line=screen->scan_line(y)+x; int sw=screen->width(); x1-=x; x2-=x; for (;ysteps>0;ysteps--) { register int ix,slam_length; for (ix=0;ixx2) // see if this run is totally clipped { datap+=slam_length; ix+=slam_length; } else { if (ix=slam_length) // see if we chopped it all off { // yes, we did ix+=slam_length; // advance everything to the end of run datap+=slam_length; slam_length=0; } else { slam_length-=chop_length; // else advance everything to begining of slam ix+=chop_length; datap+=chop_length; } } if (slam_length) // see if there is anything left to slam { register int counter; if (ix+slam_length>x2) // see if right side needs to be chopped off counter=x2-ix+1; else counter=slam_length; register uint8_t *sl=screen_line+ix,*sl2=datap; ix+=slam_length; datap+=slam_length; while (counter) { counter--; *(sl)=remap2[remap[*(sl2)]]; sl++; sl2++; } } } } } screen_line+=sw; } } void trans_image::put_fade(image *screen, int x, int y, int frame_on, int total_frames, color_filter *f, palette *pal) { int16_t x1,y1,x2,y2; int ix,slam_length,chop_length,ysteps; screen->get_clip(x1,y1,x2,y2); uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps), *screen_line; if (!datap) return ; uint8_t *screen_run,*paddr=(uint8_t *)pal->addr(), *caddr1,*caddr2,r_dest,g_dest,b_dest; long fixmul=(frame_on<<16)/total_frames; for (;ysteps>0;ysteps--,y++) { screen_line=screen->scan_line(y); for (ix=0;ixx2) // see if this run is totally clipped { datap+=slam_length; ix+=slam_length; } else { if (x+ix=slam_length) // see if we chopped it all off { // yes, we did ix+=slam_length; // advance everything to the end of run datap+=slam_length; slam_length=0; } else { slam_length-=chop_length; // else advance everything to begining of slam ix+=chop_length; datap+=chop_length; } } if (slam_length) // see if there is anything left to slam { if (x+ix+slam_length>x2) // see if right side needs to be chopped off chop_length=x2-x-ix; else chop_length=slam_length; screen_run=screen_line+x+ix; slam_length-=chop_length; ix+=chop_length; while (chop_length--) { caddr1=paddr+(int)(*screen_run)*3; caddr2=paddr+(int)(*datap)*3; r_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2); caddr1++; caddr2++; g_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2); caddr1++; caddr2++; b_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2); *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3); screen_run++; datap++; } datap+=slam_length; ix+=slam_length; } } } } } } void trans_image::put_fade_tint(image *screen, int x, int y, int frame_on, int total_frames, uint8_t *tint, color_filter *f, palette *pal) { int16_t x1,y1,x2,y2; int ix,slam_length,chop_length,ysteps; screen->get_clip(x1,y1,x2,y2); uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps), *screen_line; if (!datap) return ; uint8_t *screen_run,*paddr=(uint8_t *)pal->addr(), *caddr1,*caddr2,r_dest,g_dest,b_dest; long fixmul=(frame_on<<16)/total_frames; for (;ysteps>0;ysteps--,y++) { screen_line=screen->scan_line(y); for (ix=0;ixx2) // see if this run is totally clipped { datap+=slam_length; ix+=slam_length; } else { if (x+ix=slam_length) // see if we chopped it all off { // yes, we did ix+=slam_length; // advance everything to the end of run datap+=slam_length; slam_length=0; } else { slam_length-=chop_length; // else advance everything to begining of slam ix+=chop_length; datap+=chop_length; } } if (slam_length) // see if there is anything left to slam { if (x+ix+slam_length>x2) // see if right side needs to be chopped off chop_length=x2-x-ix; else chop_length=slam_length; screen_run=screen_line+x+ix; slam_length-=chop_length; ix+=chop_length; while (chop_length--) { caddr1=paddr+(int)(*screen_run)*3; caddr2=paddr+(int)(tint[*datap])*3; r_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2); caddr1++; caddr2++; g_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2); caddr1++; caddr2++; b_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2); *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3); screen_run++; datap++; } datap+=slam_length; ix+=slam_length; } } } } } } void trans_image::put_color(image *screen, int x, int y, int color) { int16_t x1,y1,x2,y2; int ix,slam_length,chop_length,ysteps; screen->get_clip(x1,y1,x2,y2); uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps), *screen_line; if (!datap) return ; for (;ysteps>0;ysteps--,y++) { screen_line=screen->scan_line(y); for (ix=0;ixx2) // see if this run is totally clipped { datap+=slam_length; ix+=slam_length; } else { if (x+ix=slam_length) // see if we chopped it all off { // yes, we did ix+=slam_length; // advance everything to the end of run datap+=slam_length; slam_length=0; } else { slam_length-=chop_length; // else advance everything to begining of slam ix+=chop_length; datap+=chop_length; } } if (slam_length) // see if there is anything left to slam { if (x+ix+slam_length>x2) // see if right side needs to be chopped off memset(screen_line+x+ix,color,x2-x-ix+1); else memset(screen_line+x+ix,color,slam_length); datap+=slam_length; ix+=slam_length; } } } } } } // ASSUMES that the blend image completly covers this image void trans_image::put_blend16(image *screen, image *blend, int x, int y, int blendx, int blendy, int blend_amount, color_filter *f, palette *pal) { int16_t x1,y1,x2,y2; int ix,slam_length,chop_length,ysteps; uint8_t *paddr=(uint8_t *)pal->addr(); screen->get_clip(x1,y1,x2,y2); uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps), *blend_line,*screen_line; if (!datap) return ; CONDITION(y>=blendy && y+ystepsheight()+1,"Blend doesn't fit on trans_image"); blend_amount=16-blend_amount; for (;ysteps>0;ysteps--,y++) { screen_line=screen->scan_line(y); blend_line=blend->scan_line(y-blendy); for (ix=0;ixx2) // see if this run is totally clipped { datap+=slam_length; ix+=slam_length; } else { if (x+ix=slam_length) // see if we chopped it all off { // yes, we did ix+=slam_length; // advance everything to the end of run datap+=slam_length; slam_length=0; } else { slam_length-=chop_length; // else advance everything to begining of slam ix+=chop_length; datap+=chop_length; } } if (slam_length) // see if there is anything left to slam { if (x+ix+slam_length>x2) // see if right side needs to be chopped off chop_length=x2-x-ix; else chop_length=slam_length; uint8_t *screen_run=screen_line+x+ix, *blend_run=blend_line+x+ix-blendx, *caddr1,*caddr2,r_dest,g_dest,b_dest; slam_length-=chop_length; ix+=chop_length; while (chop_length--) { caddr1=paddr+(int)(*blend_run)*3; caddr2=paddr+(int)(*datap)*3; r_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2); caddr1++; caddr2++; g_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2); caddr1++; caddr2++; b_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2); *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3); screen_run++; blend_run++; datap++; } datap+=slam_length; ix+=slam_length; } } } } } } void trans_image::put_predator(image *screen, int x, int y) { int16_t x1,y1,x2,y2; int chop_length,ysteps; screen->get_clip(x1,y1,x2,y2); register uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line; if (!datap) return ; // if clip_y says nothing to draw, return // see if the last scanline is clipped off if (y+ysteps==y2) ysteps-=2; else if (y+ysteps==y2-1) ysteps--; /* { for (int x=0;xscan_line(y)+x; int sw=screen->width(); x1-=x; x2-=x; for (;ysteps>0;ysteps--) { register int ix,slam_length; for (ix=0;ixx2) // see if this run is totally clipped { datap+=slam_length; ix+=slam_length; } else { if (ix=slam_length) // see if we chopped it all off { // yes, we did ix+=slam_length; // advance everything to the end of run datap+=slam_length; slam_length=0; } else { slam_length-=chop_length; // else advance everything to begining of slam ix+=chop_length; datap+=chop_length; } } if (slam_length) // see if there is anything left to slam { if (ix+slam_length>x2) // see if right side needs to be chopped off memcpy(screen_line+ix,screen_line+sw+sw+ix,x2-ix+1); else memcpy(screen_line+ix,screen_line+sw+sw+ix,slam_length); datap+=slam_length; ix+=slam_length; } } } } screen_line+=sw; } } int trans_image::size() { uint8_t *d=data; int t=0; for (int y=0;y