/* * Abuse - dark 2D side-scrolling platform game * Copyright (c) 1995 Crack dot Com * Copyright (c) 2005-2011 Sam Hocevar * * 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 "common.h" #include "timage.h" void trans_image::make_color(int c) { uint8_t *dp=data; int y,x; for (y=0; yLock(); uint8_t *d=im->scan_line(0),*dp=data,*dline; int y,x; for (y=0; ynext_line(y,d); } im->Unlock(); return im; } trans_image::trans_image(image *im, char const *name) { int size=0,x,y; uint8_t *sl,*datap,*marker; w=im->Size().x; h=im->Size().y; im->Lock(); // first we must find out how much data to allocate for (y=0; ySize().y; y++) { sl=im->scan_line(y); x=0; while (xSize().x,hh=im->Size().y; datap=data; if (!datap) { printf("size = %d %d (%d)\n",im->Size().x,im->Size().y,size); } CONDITION(datap,"malloc error for trans_image::data"); for (y=0; yscan_line(y); x=0; while (xSize().x && (*sl)==0) { sl++; x++; (*datap)++; } datap++; if (xSize().x && (*sl)!=0) { (*marker)++; (*datap)=*sl; datap++; x++; sl++; } } } } im->Unlock(); } void trans_image::put_scan_line(image *screen, int x, int y, int line) // always transparent { int x1, y1, x2, y2; screen->GetClip(x1, y1, x2, y2); if (y + line < y1 || y + line >= y2 || x >= x2 || x + w - 1 < x1) return; // clipped off completely? uint8_t *datap=data; int ix; while (line) // skip scan line data until we get to the line of interest { for (ix=0; ixLock(); uint8_t *screen_line=screen->scan_line(y)+x; for (ix=0; ix= x2) // clipped totally on the right? { screen->Unlock(); return ; // we are done, return! } else if (x + ix + run_length > x2) // partially clipped? { memcpy(screen_line, datap, x + ix + run_length - x2); // slam what we can screen->Unlock(); 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; } } } } screen->Unlock(); } uint8_t *trans_image::ClipToLine(image *screen, int x1, int y1, int x2, int y2, int x, int &y, int &ysteps) { // check to see if it is totally clipped out first if (y + h <= y1 || y >= y2 || x >= x2 || x + w <= x1) return NULL; uint8_t *parser = data; int skiplines = Max(y1 - y, 0); // number of lines to skip ysteps = Min(y2 - y, height() - skiplines); // number of lines to draw y += skiplines; // first line to draw while (skiplines--) { for (int ix = 0; ix < w; ) { ix += *parser++; // skip over empty space if (ix >= w) break; ix += *parser; parser += *parser + 1; // skip over data } } screen->AddDirty(Max(x, x1), y, Min(x + width(), x2), y + h); return parser; } void trans_image::put_image_filled(image *screen, int x, int y, uint8_t fill_color) { int x1, y1, x2, y2; int chop_length,ysteps; screen->GetClip(x1, y1, x2, y2); uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps), *screen_line; if (!datap) return; // if ClipToLine says nothing to draw, return screen->Lock(); screen_line=screen->scan_line(y)+x; int sw=screen->Size().x-w; x1 -= x; x2 -= x; for (; ysteps>0; ysteps--) { int ix,slam_length; for (ix=0; ix= x2) // 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); else memcpy(screen_line,datap,slam_length); datap+=slam_length; ix+=slam_length; screen_line+=slam_length; } } } } screen_line+=sw; } screen->Unlock(); } 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; uint8_t skip,*datap=data; screen->Lock(); screen_skip = screen->Size().x - w; for (; ysteps; ysteps--) { for (ix=0; ixscan_line(0)) printf("bad write in trans_image::put_image_offseted"); if (ix=screen->scan_line(screen->Size().y+1)) printf("bad write in trans_image::put_image_offseted"); } } s_off+=screen_skip; } screen->Unlock(); } void trans_image::put_image(image *screen, int x, int y) { int x1, y1, x2, y2; int chop_length,ysteps; screen->GetClip(x1, y1, x2, y2); uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps), *screen_line; if (!datap) return; // if ClipToLine says nothing to draw, return screen->Lock(); screen_line=screen->scan_line(y)+x; int sw=screen->Size().x; x1 -= x; x2 -= x; for (; ysteps>0; ysteps--) { int ix,slam_length; for (ix=0; ix= x2) // 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); else memcpy(screen_line+ix,datap,slam_length); datap+=slam_length; ix+=slam_length; } } } } screen_line+=sw; } screen->Unlock(); } void trans_image::put_remaped(image *screen, int x, int y, uint8_t *remap) { int x1, y1, x2, y2; int chop_length, ysteps; screen->GetClip(x1, y1, x2, y2); uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps), *screen_line; if (!datap) return; // if ClipToLine says nothing to draw, return screen->Lock(); screen_line=screen->scan_line(y)+x; int sw=screen->Size().x; x1 -= x; x2 -= x; for (; ysteps>0; ysteps--) { int ix,slam_length; for (ix=0; ix= x2) // 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 { int counter; if (ix + slam_length >= x2) // see if right side needs to be chopped off counter = x2 - ix; else counter = slam_length; 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; } screen->Unlock(); } void trans_image::put_double_remaped(image *screen, int x, int y, uint8_t *remap, uint8_t *remap2) { int x1, y1, x2, y2; int chop_length, ysteps; screen->GetClip(x1, y1, x2, y2); uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps), *screen_line; if (!datap) return; // if ClipToLine says nothing to draw, return screen->Lock(); screen_line=screen->scan_line(y)+x; int sw=screen->Size().x; x1 -= x; x2 -= x; for (; ysteps>0; ysteps--) { int ix,slam_length; for (ix=0; ix= x2) // 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 { int counter; if (ix + slam_length >= x2) // see if right side needs to be chopped off counter = x2 - ix; else counter = slam_length; 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; } screen->Unlock(); } void trans_image::put_fade(image *screen, int x, int y, int frame_on, int total_frames, color_filter *f, palette *pal) { int x1, y1, x2, y2; int ix,slam_length,chop_length,ysteps; screen->GetClip(x1, y1, x2, y2); uint8_t *datap = ClipToLine(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; screen->Lock(); for (; ysteps>0; ysteps--,y++) { screen_line=screen->scan_line(y); for (ix=0; ix= x2) // 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 - 1 - 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; } } } } } screen->Unlock(); } 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) { int x1, y1, x2, y2; int ix,slam_length,chop_length,ysteps; screen->GetClip(x1, y1, x2, y2); uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps), *screen_line; if (!datap) return; screen->Lock(); 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; ix= x2) // 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 - 1 - 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; } } } } } screen->Unlock(); } void trans_image::put_color(image *screen, int x, int y, int color) { int x1, y1, x2, y2; int ix,slam_length,chop_length,ysteps; screen->GetClip(x1, y1, x2, y2); uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps), *screen_line; if (!datap) return; screen->Lock(); for (; ysteps>0; ysteps--,y++) { screen_line=screen->scan_line(y); for (ix=0; ix= x2) // 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); else memset(screen_line + x + ix, color, slam_length); datap+=slam_length; ix+=slam_length; } } } } } screen->Unlock(); } // 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) { int x1, y1, x2, y2; int ix,slam_length,chop_length,ysteps; uint8_t *paddr=(uint8_t *)pal->addr(); screen->GetClip(x1, y1, x2, y2); uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps), *blend_line, *screen_line; if (!datap) return; CONDITION(y>=blendy && y+ystepsSize().y+1,"Blend doesn't fit on trans_image"); blend_amount=16-blend_amount; screen->Lock(); for (; ysteps>0; ysteps--,y++) { screen_line=screen->scan_line(y); blend_line=blend->scan_line(y-blendy); for (ix=0; ix= x2) // 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 - 1 - 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; } } } } } screen->Unlock(); } void trans_image::put_predator(image *screen, int x, int y) { int x1, y1, x2, y2; int chop_length,ysteps; screen->GetClip(x1, y1, x2, y2); uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps), *screen_line; if (!datap) return; // if ClipToLine says nothing to draw, return // see if the last scanline is clipped off if (y + ysteps == y2 - 1) ysteps -= 2; else if (y + ysteps == y2 - 2) ysteps--; /* { for (int x=0; xLock(); screen_line=screen->scan_line(y)+x; int sw=screen->Size().x; x1 -= x; x2 -= x; for (; ysteps>0; ysteps--) { int ix,slam_length; for (ix=0; ix= x2) // 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); else memcpy(screen_line + ix, screen_line + sw + sw + ix, slam_length); datap+=slam_length; ix+=slam_length; } } } } screen_line+=sw; } screen->Unlock(); } int trans_image::size() { uint8_t *d=data; int t=0; for (int y=0; y