#include "globals.h"
#include "water.h"

#define _getpixel8 _getpixel
#define _putpixel8 _putpixel

#if 0
void SWater(BITMAP *water1,BITMAP *water2,int x,int y,int sx,int sy,int sw,int sh,int DX,int DY)
{
  int i,j;
  int c;
  int dx,dy;
  int r,g,b;
  int *toptr;
  unsigned char *ptr;
  unsigned char *prev_ptr;
  unsigned char *ptr_m;
  unsigned char *ptr_s;
  unsigned char *ptr_p;

  for (j=sy/WATERSCALE+1;j<sy/WATERSCALE+sh/WATERSCALE-1;j++) {
    ptr=water1->line[j]+sx/WATERSCALE+1;
    prev_ptr=water1->line[j-1]+sx/WATERSCALE+1;
    ptr_m=water2->line[j-1]+sx/WATERSCALE+1;
    ptr_s=water2->line[j]+sx/WATERSCALE+1;
    ptr_p=water2->line[j+1]+sx/WATERSCALE+1;
    for (i=sx/WATERSCALE+1;i<sx/WATERSCALE+sw/WATERSCALE-1;i++) {
      c=*(ptr_m-1)+*ptr_m+*(ptr_m+1);
      c+=*(ptr_s-1)+*(ptr_s+1);
      c+=*(ptr_p-1)+*ptr_p+*(ptr_p+1);
      c-=4*(*ptr);
      c/=4;
      c=c-(c>>2);
      c=MID(0,c,255);
      _putpixel(water1,i-DX,j-DY,c);
      ptr++;
      ptr_m++;
      ptr_s++;
      ptr_p++;
      prev_ptr++;

      dx=*ptr-*(ptr-1);
      dy=*ptr-*prev_ptr;
      c=_getpixel16(
        bg,((1<<16)+i*WATERSCALE+dx+x)&255,((1<<16)+j*WATERSCALE+dy+y)&127
      );
      r=getr16(c);
      g=getg16(c);
      b=getb16(c);
      r=r-dx/2;
      r=MID(0,r,255);
      g=g-dx/2;
      g=MID(0,g,255);
      b=b-dx/2;
      b=MID(0,b,255);
      c=makecol16(r,g,b);

      c=c+(c<<16);
      toptr=(int*)(drawable->line[j*WATERSCALE])+(i*WATERSCALE/2);
      *toptr=c;
      *(toptr+1)=c;
      toptr=(int*)(drawable->line[j*WATERSCALE+1])+(i*WATERSCALE/2);
      *toptr=c;
      *(toptr+1)=c;
      toptr=(int*)(drawable->line[j*WATERSCALE+2])+(i*WATERSCALE/2);
      *toptr=c;
      *(toptr+1)=c;
      toptr=(int*)(drawable->line[j*WATERSCALE+3])+(i*WATERSCALE/2);
      *toptr=c;
      *(toptr+1)=c;
    }
  }
}
#endif


#define SWATER(bpp,write) \
void SWater##bpp(BITMAP *water1,BITMAP *water2,int x,int y,int sx,int sy,int sw,int sh,int DX,int DY) \
{ \
  int i,j; \
  int c; \
  int dx,dy; \
  int r,g,b; \
  int *toptr; \
  unsigned char *ptr; \
  unsigned char *prev_ptr; \
  unsigned char *ptr_m; \
  unsigned char *ptr_s; \
  unsigned char *ptr_p; \
 \
  for (j=sy/WATERSCALE+1;j<sy/WATERSCALE+sh/WATERSCALE-1;j++) { \
    ptr=water1->line[j+BORDER]+sx/WATERSCALE+1+BORDER; \
    prev_ptr=water1->line[j-1+BORDER]+sx/WATERSCALE+1+BORDER; \
    ptr_m=water2->line[j-1+BORDER]+sx/WATERSCALE+1+BORDER; \
    ptr_s=water2->line[j+BORDER]+sx/WATERSCALE+1+BORDER; \
    ptr_p=water2->line[j+1+BORDER]+sx/WATERSCALE+1+BORDER; \
    for (i=sx/WATERSCALE+1;i<sx/WATERSCALE+sw/WATERSCALE-1;i++) { \
      c=*(ptr_m-1)+*ptr_m+*(ptr_m+1); \
      c+=*(ptr_s-1)+*(ptr_s+1); \
      c+=*(ptr_p-1)+*ptr_p+*(ptr_p+1); \
      c/=4; \
      c-=*ptr; \
      c=c-(c>>2); \
      c=MID(0,c,255); \
      _putpixel(water1,i-DX+BORDER,j-DY+BORDER,c); \
      ptr++; \
      ptr_m++; \
      ptr_s++; \
      ptr_p++; \
      prev_ptr++; \
 \
      dx=*ptr-*(ptr-1); \
      dy=*ptr-*prev_ptr; \
      c=_getpixel##bpp( \
        bg,((1<<16)+i*WATERSCALE+dx+x)&255,((1<<16)+j*WATERSCALE+dy+y)&127 \
      ); \
 \
      write \
    } \
  } \
}


#define WRITE8 \
      c+=dx/2; \
      c+=128; \
      c=MID(64,c,191); \
      c=c+(c<<8)+(c<<16)+(c<<24); \
      toptr=(int*)(drawable->line[j*WATERSCALE])+(i*WATERSCALE/4); \
      *toptr=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE+1])+(i*WATERSCALE/4); \
      *toptr=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE+2])+(i*WATERSCALE/4); \
      *toptr=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE+3])+(i*WATERSCALE/4); \
      *toptr=c;

#define WRITE15 \
      r=getr15(c); \
      g=getg15(c); \
      b=getb15(c); \
      r=r+dx/2; \
      r=MID(0,r,255); \
      g=g+dx/2; \
      g=MID(0,g,255); \
      b=b+dx/2; \
      b=MID(0,b,255); \
      c=makecol15(r,g,b); \
      c=c+(c<<16); \
      toptr=(int*)(drawable->line[j*WATERSCALE])+(i*WATERSCALE/2); \
      *toptr=c; \
      *(toptr+1)=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE+1])+(i*WATERSCALE/2); \
      *toptr=c; \
      *(toptr+1)=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE+2])+(i*WATERSCALE/2); \
      *toptr=c; \
      *(toptr+1)=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE+3])+(i*WATERSCALE/2); \
      *toptr=c; \
      *(toptr+1)=c;

#define WRITE16 \
      r=getr16(c); \
      g=getg16(c); \
      b=getb16(c); \
      r=r+dx/2; \
      r=MID(0,r,255); \
      g=g+dx/2; \
      g=MID(0,g,255); \
      b=b+dx/2; \
      b=MID(0,b,255); \
      c=makecol16(r,g,b); \
      c=c+(c<<16); \
      toptr=(int*)(drawable->line[j*WATERSCALE])+(i*WATERSCALE/2); \
      *toptr=c; \
      *(toptr+1)=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE+1])+(i*WATERSCALE/2); \
      *toptr=c; \
      *(toptr+1)=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE+2])+(i*WATERSCALE/2); \
      *toptr=c; \
      *(toptr+1)=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE+3])+(i*WATERSCALE/2); \
      *toptr=c; \
      *(toptr+1)=c;


#define WRITE24 \
      r=getr24(c); \
      g=getg24(c); \
      b=getb24(c); \
      r=r+dx/2; \
      r=MID(0,r,255); \
      g=g+dx/2; \
      g=MID(0,g,255); \
      b=b+dx/2; \
      b=MID(0,b,255); \
      c=makecol24(r,g,b); \
      unsigned long addr; \
      addr=bmp_write_line(drawable,j*WATERSCALE)+(i*WATERSCALE)*3; \
      bmp_write24(addr,c); \
      bmp_write24(addr+3,c); \
      bmp_write24(addr+6,c); \
      bmp_write24(addr+9,c); \
      bmp_write24(addr+12,c); \
      addr=bmp_write_line(drawable,j*WATERSCALE+1)+(i*WATERSCALE)*3; \
      bmp_write24(addr,c); \
      bmp_write24(addr+3,c); \
      bmp_write24(addr+6,c); \
      bmp_write24(addr+9,c); \
      bmp_write24(addr+12,c); \
      addr=bmp_write_line(drawable,j*WATERSCALE+2)+(i*WATERSCALE)*3; \
      bmp_write24(addr,c); \
      bmp_write24(addr+3,c); \
      bmp_write24(addr+6,c); \
      bmp_write24(addr+9,c); \
      bmp_write24(addr+12,c); \
      addr=bmp_write_line(drawable,j*WATERSCALE+3)+(i*WATERSCALE)*3; \
      bmp_write24(addr,c); \
      bmp_write24(addr+3,c); \
      bmp_write24(addr+6,c); \
      bmp_write24(addr+9,c); \
      bmp_write24(addr+12,c); \

#define WRITE32 \
      r=getr32(c); \
      g=getg32(c); \
      b=getb32(c); \
      r=r+dx/2; \
      r=MID(0,r,255); \
      g=g+dx/2; \
      g=MID(0,g,255); \
      b=b+dx/2; \
      b=MID(0,b,255); \
      c=makecol32(r,g,b); \
      toptr=(int*)(drawable->line[j*WATERSCALE])+(i*WATERSCALE); \
      *toptr=c; \
      *(toptr+1)=c; \
      *(toptr+2)=c; \
      *(toptr+3)=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE+1])+(i*WATERSCALE); \
      *toptr=c; \
      *(toptr+1)=c; \
      *(toptr+2)=c; \
      *(toptr+3)=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE+2])+(i*WATERSCALE); \
      *toptr=c; \
      *(toptr+1)=c; \
      *(toptr+2)=c; \
      *(toptr+3)=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE+3])+(i*WATERSCALE); \
      *toptr=c; \
      *(toptr+1)=c; \
      *(toptr+2)=c; \
      *(toptr+3)=c;

SWATER(8,WRITE8)
SWATER(15,WRITE15)
SWATER(16,WRITE16)
SWATER(24,WRITE24)
SWATER(32,WRITE32)

void SWater(BITMAP *water1,BITMAP *water2,int x,int y,int sx,int sy,int sw,int sh,int DX,int DY)
{
  set_clip(
    water1,
    sx/WATERSCALE+BORDER,sy/WATERSCALE+BORDER,
    (sx+sw)/WATERSCALE-1+BORDER,(sy+sh)/WATERSCALE-1+BORDER
  );
  if (DX>BORDER) {
    //Log("ERROR: DX == %d\n",DX);
    //allegro_message("\007");
    DX=BORDER;
  }
  if (DX<-BORDER) {
    //Log("ERROR: DX == %d\n",DX);
    //allegro_message("\007");
    DX=-BORDER;
  }
  if (DY>BORDER) {
    //Log("ERROR: DY == %d\n",DY);
    //allegro_message("\007");
    DY=BORDER;
  }
  if (DY<-BORDER) {
    //Log("ERROR: DY == %d\n",DY);
    //allegro_message("\007");
    DY=-BORDER;
  }
  switch (_color_depth) {
    case 8:SWater8(water1,water2,x,y,sx,sy,sw,sh,DX,DY);break;
    case 15:SWater15(water1,water2,x,y,sx,sy,sw,sh,DX,DY);break;
    case 16:SWater16(water1,water2,x,y,sx,sy,sw,sh,DX,DY);break;
    case 24:SWater24(water1,water2,x,y,sx,sy,sw,sh,DX,DY);break;
    case 32:SWater32(water1,water2,x,y,sx,sy,sw,sh,DX,DY);break;
  }
}

/*
void SWaterScreen(BITMAP *water1,BITMAP *water2,int x,int y,int sx,int sy,int sw,int sh)
{
  SWater(water1,water2,x,y,sx,sy,sw,sh,0,0);
}
*/

#if 0
#define SWATERSCREEN(bpp,write) \
void SWaterScreen##bpp(BITMAP *water1,BITMAP *water2,int x,int y,int sx,int sy,int sw,int sh) \
{ \
  int i,j; \
  int c; \
  int dx,dy; \
  int r,g,b; \
 \
  for (j=sy/WATERSCALE2+1;j<sy/WATERSCALE2+sh/WATERSCALE2-1;j++) { \
    for (i=sx/WATERSCALE2+1;i<sx/WATERSCALE2+sw/WATERSCALE2-1;i++) { \
      c=-4*_getpixel(water1,i,j) \
          +_getpixel(water2,i-1,j-1) \
          +_getpixel(water2,i,j-1) \
          +_getpixel(water2,i+1,j-1) \
          +_getpixel(water2,i-1,j) \
          +_getpixel(water2,i+1,j) \
          +_getpixel(water2,i-1,j+1) \
          +_getpixel(water2,i,j+1) \
          +_getpixel(water2,i+1,j+1); \
      c/=4; \
      c=c-(c>>2); \
      c=MID(0,c,255); \
      _putpixel(water1,i,j,c); \
    } \
  } \
 \
  for (j=sy/WATERSCALE2+1;j<sy/WATERSCALE2+sh/WATERSCALE2-1;j++) { \
    for (i=sx/WATERSCALE2+1;i<sx/WATERSCALE2+sw/WATERSCALE2-1;i++) { \
      dx=_getpixel(water1,i,j)-_getpixel(water1,i+1,j); \
      dy=_getpixel(water1,i,j)-_getpixel(water1,i,j+1); \
      c=getpixel( \
        bg,((1<<16)+i*WATERSCALE2+dx+x)&255,((1<<16)+j*WATERSCALE2+dy+y)&127 \
      ); \
      write \
    } \
  } \
}
#endif

#define SWATERSCREEN(bpp,write) \
void SWaterScreen##bpp(BITMAP *water1,BITMAP *water2,int x,int y,int sx,int sy,int sw,int sh) \
{ \
  int i,j; \
  int c; \
  int dx,dy; \
  int r,g,b; \
  int *toptr; \
  unsigned char *ptr; \
  unsigned char *prev_ptr; \
  unsigned char *ptr_m; \
  unsigned char *ptr_s; \
  unsigned char *ptr_p; \
 \
  for (j=sy/WATERSCALE2+1;j<sy/WATERSCALE2+sh/WATERSCALE2-1;j++) { \
    ptr=water1->line[j+BORDER]+sx/WATERSCALE2+1+BORDER; \
    prev_ptr=water1->line[j-1+BORDER]+sx/WATERSCALE2+1+BORDER; \
    ptr_m=water2->line[j-1+BORDER]+sx/WATERSCALE2+1+BORDER; \
    ptr_s=water2->line[j+BORDER]+sx/WATERSCALE2+1+BORDER; \
    ptr_p=water2->line[j+1+BORDER]+sx/WATERSCALE2+1+BORDER; \
    for (i=sx/WATERSCALE2+1;i<sx/WATERSCALE2+sw/WATERSCALE2-1;i++) { \
      c=*(ptr_m-1)+*ptr_m+*(ptr_m+1); \
      c+=*(ptr_s-1)+*(ptr_s+1); \
      c+=*(ptr_p-1)+*ptr_p+*(ptr_p+1); \
      c/=4; \
      c-=*ptr; \
      c=c-(c>>2); \
      c=MID(0,c,255); \
      _putpixel(water1,i+BORDER,j+BORDER,c); \
      ptr++; \
      ptr_m++; \
      ptr_s++; \
      ptr_p++; \
      prev_ptr++; \
 \
      dx=*ptr-*(ptr-1); \
      dy=*ptr-*prev_ptr; \
      c=_getpixel##bpp( \
        bg,((1<<16)+i*WATERSCALE2+dx+x)&255,((1<<16)+j*WATERSCALE2+dy+y)&127 \
      ); \
 \
      write \
    } \
  } \
}


#define SWRITE8 \
      c+=dx/2; \
      c+=128; \
      c=MID(64,c,191); \
      unsigned char *toptr2; \
      toptr2=drawable->line[j*WATERSCALE2]+i*WATERSCALE2; \
      *toptr2=c; \
      *(toptr2+1)=c; \
      toptr2=drawable->line[j*WATERSCALE2+1]+i*WATERSCALE2; \
      *toptr2=c; \
      *(toptr2+1)=c; \
      toptr2=drawable->line[j*WATERSCALE2+2]+i*WATERSCALE2; \
      *toptr2=c; \
      *(toptr2+1)=c; \
      toptr2=drawable->line[j*WATERSCALE2+3]+i*WATERSCALE2; \
      *toptr2=c; \
      *(toptr2+1)=c;

#define SWRITE15 \
      r=getr15(c); \
      g=getg15(c); \
      b=getb15(c); \
      r=r+dx/2; \
      r=MID(0,r,255); \
      g=g+dx/2; \
      g=MID(0,g,255); \
      b=b+dx/2; \
      b=MID(0,b,255); \
      c=makecol15(r,g,b); \
      c=c+(c<<16); \
      toptr=(int*)(drawable->line[j*WATERSCALE2])+(i*WATERSCALE2/2); \
      *toptr=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE2+1])+(i*WATERSCALE2/2); \
      *toptr=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE2+2])+(i*WATERSCALE2/2); \
      *toptr=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE2+3])+(i*WATERSCALE2/2); \
      *toptr=c; \

#define SWRITE16 \
      r=getr16(c); \
      g=getg16(c); \
      b=getb16(c); \
      r=r+dx/2; \
      r=MID(0,r,255); \
      g=g+dx/2; \
      g=MID(0,g,255); \
      b=b+dx/2; \
      b=MID(0,b,255); \
      c=makecol16(r,g,b); \
      c=c+(c<<16); \
      toptr=(int*)(drawable->line[j*WATERSCALE2])+(i*WATERSCALE2/2); \
      *toptr=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE2+1])+(i*WATERSCALE2/2); \
      *toptr=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE2+2])+(i*WATERSCALE2/2); \
      *toptr=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE2+3])+(i*WATERSCALE2/2); \
      *toptr=c;


#define SWRITE24 \
      r=getr24(c); \
      g=getg24(c); \
      b=getb24(c); \
      r=r+dx/2; \
      r=MID(0,r,255); \
      g=g+dx/2; \
      g=MID(0,g,255); \
      b=b+dx/2; \
      b=MID(0,b,255); \
      c=makecol24(r,g,b); \
      unsigned long addr; \
      addr=bmp_write_line(drawable,j*WATERSCALE2)+(i*WATERSCALE2)*3; \
      bmp_write24(addr,c); \
      bmp_write24(addr+3,c); \
      addr=bmp_write_line(drawable,j*WATERSCALE2+1)+(i*WATERSCALE2)*3; \
      bmp_write24(addr,c); \
      bmp_write24(addr+3,c); \
      addr=bmp_write_line(drawable,j*WATERSCALE2+2)+(i*WATERSCALE2)*3; \
      bmp_write24(addr,c); \
      bmp_write24(addr+3,c); \
      addr=bmp_write_line(drawable,j*WATERSCALE2+3)+(i*WATERSCALE2)*3; \
      bmp_write24(addr,c); \
      bmp_write24(addr+3,c);

#define SWRITE32 \
      r=getr32(c); \
      g=getg32(c); \
      b=getb32(c); \
      r=r+dx/2; \
      r=MID(0,r,255); \
      g=g+dx/2; \
      g=MID(0,g,255); \
      b=b+dx/2; \
      b=MID(0,b,255); \
      c=makecol32(r,g,b); \
      toptr=(int*)(drawable->line[j*WATERSCALE2])+(i*WATERSCALE2); \
      *toptr=c; \
      *(toptr+1)=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE2+1])+(i*WATERSCALE2); \
      *toptr=c; \
      *(toptr+1)=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE2+2])+(i*WATERSCALE2); \
      *toptr=c; \
      *(toptr+1)=c; \
      toptr=(int*)(drawable->line[j*WATERSCALE2+3])+(i*WATERSCALE2); \
      *toptr=c; \
      *(toptr+1)=c;


SWATERSCREEN(8,SWRITE8)
SWATERSCREEN(15,SWRITE15)
SWATERSCREEN(16,SWRITE16)
SWATERSCREEN(24,SWRITE24)
SWATERSCREEN(32,SWRITE32)

void SWaterScreen(BITMAP *water1,BITMAP *water2,int x,int y,int sx,int sy,int sw,int sh)
{
  set_clip(
    water1,
    sx/WATERSCALE2+BORDER,sy/WATERSCALE2+BORDER,
    (sx+sw)/WATERSCALE2-1+BORDER,(sy+sh)/WATERSCALE2-1+BORDER
  );
  switch (_color_depth) {
    case 8:SWaterScreen8(water1,water2,x,y,sx,sy,sw,sh);break;
    case 15:SWaterScreen15(water1,water2,x,y,sx,sy,sw,sh);break;
    case 16:SWaterScreen16(water1,water2,x,y,sx,sy,sw,sh);break;
    case 24:SWaterScreen24(water1,water2,x,y,sx,sy,sw,sh);break;
    case 32:SWaterScreen32(water1,water2,x,y,sx,sy,sw,sh);break;
  }
}
