/*
* Darken a bitmap
*/
#include "ithelib.h"
#include <allegro.h>
// Defines
// Variables
COLOR_MAP light_cmap;
COLOR_MAP dark_cmap;
static unsigned short *coltab16;
static unsigned char *coltab8;
static unsigned short *lightning16;
void (*darken)(BITMAP *image, BITMAP *tab, int w, int h);
void (*darken_s)(BITMAP *image, unsigned int level, int w, int h);
void (*darken_blit)(unsigned char *dest, unsigned char *src, int h);
void (*lightning)(BITMAP *image);
// Functions
void darken_init(int bpp);
static void darken_8_init(void);
// We don't support 8bpp in assembler anymore
static void darken_8_c(BITMAP *image, BITMAP *tab,int w, int h);
static void darken_8s_c(BITMAP *image, unsigned int colour,int w, int h);
static void darken_blit8_c(unsigned char *dest, unsigned char *src,int pixels);
#ifdef NO_ASM
static void darken_16_c(BITMAP *image, BITMAP *tab,int w, int h);
static void darken_16s_c(BITMAP *image, unsigned int colour,int w, int h);
static void darken_blit16_c(unsigned char *dest, unsigned char *src,int pixels);
static void darken_blit32_c(unsigned char *dest, unsigned char *src,int pixels);
#else
static void darken_16_asm(BITMAP *image, BITMAP *tab,int w, int h);
static void darken_16s_asm(BITMAP *image, unsigned int colour,int w, int h);
static void darken_32_asm(BITMAP *image, BITMAP *tab,int w, int h);
static void darken_32s_asm(BITMAP *image, unsigned int colour,int w, int h);
#endif
static void darken_generic_c(BITMAP *image, BITMAP *tab,int w, int h);
static void darkens_generic_c(BITMAP *image, unsigned int level,int w, int h);
static void darken_blit_generic(unsigned char *dest, unsigned char *src,int pixels);
static void lightning_generic_c(BITMAP *image);
static void darken_16_init(void);
static void lightning_16(BITMAP *image);
static void darken_32_c(BITMAP *image, BITMAP *tab,int w, int h);
static void darken_32s_c(BITMAP *image, unsigned int colour,int w, int h);
extern void darken_asm_16(unsigned int *spr, unsigned char *darkmap, int pixels, unsigned short *lut);
extern void darken_asm_16s(unsigned int *spr, unsigned int colour, int pixels, unsigned short *lut);
extern void darken_asm_32(unsigned int *spr, unsigned char *darkmap, int pixels);
extern void darken_asm_32s(unsigned int *spr, unsigned int colour, int pixels);
extern void darken_asm_blit16(unsigned char *dest, unsigned char *src, int pixels);
extern void darken_asm_blit32(unsigned char *dest, unsigned char *src, int pixels);
// Code
void darken_init(int bpp)
{
int x,y,z;
// Choose default method for lightning
lightning=lightning_generic_c;
// Choose a method for the shading
switch(bpp)
{
case 8:
darken_8_init();
darken = darken_8_c;
darken_s = darken_8s_c;
darken_blit = darken_blit8_c;
break;
case 15:
case 16:
darken_16_init();
#ifdef NO_ASM
darken = darken_16_c;
darken_s = darken_16s_c;
darken_blit = darken_blit16_c;
#else
darken = darken_16_asm;
darken_s = darken_16s_asm;
darken_blit = darken_asm_blit16;
#endif
lightning=lightning_16;
break;
case 24:
darken = darken_generic_c;
darken_s = darkens_generic_c;
darken_blit = darken_blit_generic;
ilog_printf("WARNING: 24bpp not fully supported\n");
break;
case 32:
#ifdef NO_ASM
darken = darken_32_c;
darken_s = darken_32s_c;
darken_blit = darken_blit32_c;
#else
if(cpu_mmx)
{
darken = darken_32_asm;
darken_s = darken_32s_asm;
}
else
{
darken = darken_32_c;
darken_s = darken_32s_c;
}
darken_blit = darken_asm_blit32;
#endif
break;
default:
darken = darken_generic_c;
darken_s = darkens_generic_c;
darken_blit = darken_blit_generic;
ilog_printf("WARNING: unrecognised colour depth (%d bpp)\n",bpp);
break;
}
// Build colourmap for light sources
for(y=0;y<=255;y++)
for(x=0;x<=255;x++)
{
z=y-x;
if(z<0)
z=0;
light_cmap.data[x][y]=(unsigned char)z;
}
// Build colourmap for dark sources
for(y=0;y<=255;y++)
for(x=0;x<=255;x++)
{
z=y+x;
if(z>255)
z=255;
dark_cmap.data[x][y]=(unsigned char)z;
}
}
void darken_generic_c(BITMAP *image, BITMAP *tab,int w, int h)
{
int x,y,col,level,r,g,b;
for(y=0;y<h;y++)
for(x=0;x<w;x++)
{
col = getpixel(image,x,y);
level = _getpixel(tab,x,y);
r = getr(col);
g = getg(col);
b = getb(col);
r-= level;
if(r<0)
r=0;
g-= level;
if(g<0)
g=0;
b-= level;
if(b<0)
b=0;
putpixel(image,x,y,makecol(r,g,b));
}
}
void darkens_generic_c(BITMAP *image, unsigned int level,int w, int h)
{
int x,y,col,r,g,b;
for(y=0;y<h;y++)
for(x=0;x<w;x++)
{
col = getpixel(image,x,y);
r = getr(col);
g = getg(col);
b = getb(col);
r-= level;
if(r<0)
r=0;
g-= level;
if(g<0)
g=0;
b-= level;
if(b<0)
b=0;
putpixel(image,x,y,makecol(r,g,b));
}
}
/*
* Build the lookup table for 8 bits per pixel
*/
void darken_8_init(void)
{
int ctr,ctr2,r,g,b;
// Allocate lookup table
coltab8 = (unsigned char *)M_get(1,65536);
for(ctr=0;ctr<256;ctr++)
{
for(ctr2=0;ctr2<256;ctr2++)
{
r=getr(ctr2)-(ctr<<3);
if(r<0)
r=0;
g=getg(ctr2)-(ctr<<3);
if(g<0)
g=0;
b=getb(ctr2)-(ctr<<3);
if(b<0)
b=0;
coltab8[(ctr*256)+ctr2]=makecol(r,g,b);
}
}
}
/*
* Use the lookup table to perform the shading in 8 bpp
*/
void darken_8_c(BITMAP *image, BITMAP *tab,int w, int h)
{
unsigned int x,y;
unsigned char *iptr=(unsigned char *)image->line[0];
unsigned char *lptr=(unsigned char *)tab->line[0];
y=w*h;
for(x=0;x<y;x++)
{
*iptr = (coltab8[((*lptr++)<<8)+*iptr]);
iptr++;
}
}
void darken_8s_c(BITMAP *image, unsigned int level,int w, int h)
{
unsigned int x,y;
unsigned char *iptr=(unsigned char *)image->line[0];
y=w*h;
for(x=0;x<y;x++)
{
*iptr = (coltab8[(level<<8)+*iptr]);
iptr++;
}
}
void darken_blit8_c(unsigned char *dest, unsigned char *src, int len)
{
int ctr;
for(ctr=0;ctr<len;ctr++)
{
if(*src)
*dest=*src;
src++;
dest++;
}
}
/*
* Build the lookup table for 15 and 16 bits per pixel
*/
void darken_16_init(void)
{
int ctr,ctr2,r,g,b,out;
// Allocate lookup table
coltab16 = (unsigned short *)M_get(32,65536*sizeof(unsigned short));
for(ctr=0;ctr<32;ctr++)
{
for(ctr2=0;ctr2<65536;ctr2++)
{
r=getr(ctr2)-(ctr<<3);
if(r<0)
r=0;
g=getg(ctr2)-(ctr<<3);
if(g<0)
g=0;
b=getb(ctr2)-(ctr<<3);
if(b<0)
b=0;
out = makecol(r,g,b);
// 0 is used for Transparent in the rooftop shading code, so decide
// what needs to be done.
if(out == 0)
{
if(ctr2 == 0)
out = 0; // Make it transparent
else
out = 1; // very close to black
}
coltab16[(ctr*65536)+ctr2]= out;
}
}
// Allocate lightning table
lightning16 = (unsigned short *)M_get(1,65536*sizeof(unsigned short));
for(ctr=0;ctr<65536;ctr++)
{
r=getr(ctr)<<1;
g=getg(ctr)<<1;
b=getb(ctr)<<2;
if(r>255)
r=255;
if(g>255)
g=255;
if(b>255)
b=255;
lightning16[ctr]=makecol(r,g,b);
}
}
/*
* Use the lookup table to perform the shading in 16 or 15 bpp
*/
void darken_16_c(BITMAP *image, BITMAP *tab,int w, int h)
{
unsigned int x,y;
unsigned short *iptr=(unsigned short *)image->line[0];
unsigned char *lptr=(unsigned char *)tab->line[0];
y=w*h;
for(x=0;x<y;x++)
{
*iptr = (coltab16[(((*lptr++)&0xf8)<<13)+*iptr]);
iptr++;
}
}
void darken_16s_c(BITMAP *image, unsigned int level,int w, int h)
{
unsigned int x,y;
unsigned short *iptr=(unsigned short *)image->line[0];
level &=0xf8;
y=w*h;
for(x=0;x<y;x++)
{
*iptr = (coltab16[(level<<13)+*iptr]);
iptr++;
}
}
void darken_blit16_c(unsigned char *dest, unsigned char *src, int len)
{
int ctr;
unsigned short *d=(unsigned short *)dest;
unsigned short *s=(unsigned short *)src;
for(ctr=0;ctr<len;ctr++)
{
if(*s)
*d=*s;
s++;
d++;
}
}
/*
* Use the lookup table to perform the lightning in 16 or 15 bpp
*/
void lightning_16(BITMAP *image)
{
unsigned int x,y;
unsigned short *iptr=(unsigned short *)image->line[0];
y=image->w*image->h;
for(x=0;x<y;x++)
{
*iptr = (lightning16[*iptr]);
iptr++;
}
}
void darken_16_asm(BITMAP *image, BITMAP *tab,int w, int h)
{
#ifndef NO_ASM
darken_asm_16((unsigned int *)image->line[0],(unsigned char *)tab->line[0],w*h,coltab16);
#endif
}
void darken_16s_asm(BITMAP *image, unsigned int level,int w, int h)
{
#ifndef NO_ASM
darken_asm_16s((unsigned int *)image->line[0],level,w*h,coltab16);
#endif
}
void darken_32_asm(BITMAP *image, BITMAP *tab,int w, int h)
{
#ifndef NO_ASM
darken_asm_32((unsigned int *)image->line[0],(unsigned char *)tab->line[0],w*h);
#endif
}
void darken_32s_asm(BITMAP *image, unsigned int level,int w, int h)
{
#ifndef NO_ASM
darken_asm_32s((unsigned int *)image->line[0],level,w*h);
#endif
}
void darken_32_c(BITMAP *image, BITMAP *tab,int w, int h)
{
unsigned int x,y;
unsigned char *iptr=(unsigned char *)image->line[0];
unsigned char *lptr=(unsigned char *)tab->line[0];
y=w*h;
for(x=0;x<y;x++)
{
*iptr = (light_cmap.data[*lptr][*iptr]); // R
iptr++;
*iptr = (light_cmap.data[*lptr][*iptr]); // G
iptr++;
*iptr = (light_cmap.data[*lptr][*iptr]); // B
iptr++;
*iptr = (light_cmap.data[*lptr][*iptr]); // A
iptr++;
lptr++;
}
}
void darken_32s_c(BITMAP *image, unsigned int level,int w, int h)
{
unsigned int x,y;
unsigned char *iptr=(unsigned char *)image->line[0];
unsigned int *l = (unsigned int *)iptr;
y=w*h;
for(x=0;x<y;x++)
{
// If it was zero before, it's supposed to be translucent for the colour
// separation used by the roof overlay projector
if(*l == 0)
{
iptr+=4;
}
else
{
// Otherwise darken it and set the alpha to make sure it's non-zero
*iptr = (light_cmap.data[level][*iptr]); // R
iptr++;
*iptr = (light_cmap.data[level][*iptr]); // G
iptr++;
*iptr = (light_cmap.data[level][*iptr]); // B
iptr++;
*iptr = 0x01; // A
iptr++;
}
l++;
}
}
void darken_blit32_c(unsigned char *dest, unsigned char *src, int len)
{
int ctr;
unsigned int *d=(unsigned int *)dest;
unsigned int *s=(unsigned int *)src;
for(ctr=0;ctr<len;ctr++)
{
if(*s)
*d=*s;
s++;
d++;
}
}
void lightning_generic_c(BITMAP *image)
{
int x,y,col,r,g,b;
for(y=0;y<image->h;y++)
for(x=0;x<image->w;x++)
{
col = getpixel(image,x,y);
r = getr(col)<<1;
g = getg(col)<<1;
b = getb(col)<<2;
if(r>255)
r=255;
if(g>255)
g=255;
if(b>255)
b=255;
putpixel(image,x,y,makecol(r,g,b));
}
}
void darken_blit_generic(unsigned char *dest, unsigned char *src, int len)
{
// Do Nothing
}