/***************************************************************************
Jaleco color blend emulation
****************************************************************************
This implements the behaviour of color blending/alpha hardware
found in a small set of machines from the late 80's.
Thus far, Psychic 5, Argus, and Valtric are presumed to use it.
****************************************************************************/
#include "emu.h"
#include "jalblend.h"
/* each palette entry contains a fourth 'alpha' value */
static UINT8 *jal_blend_table;
static void jal_blend_reset(running_machine &machine)
{
memset(jal_blend_table, 0, 0xc00);
}
void jal_blend_init(running_machine &machine, int enable)
{
if (enable)
{
jal_blend_table = auto_alloc_array_clear(machine, UINT8, 0xc00);
machine.add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(jal_blend_reset), &machine));
}
else
{
jal_blend_table = NULL;
}
}
void jal_blend_set(int color, UINT8 val)
{
if (jal_blend_table) jal_blend_table[color] = val;
}
/*
* 'Alpha' Format
* ------------------
*
* Bytes | Use
* -76543210-+----------------
* ----x--- | blend enable flag (?)
* -----x-- | red add/subtract
* ------x- | green add/subtract
* -------x | blue add/subtract
*/
/* basically an add/subtract function with clamping */
rgb_t jal_blend_func(rgb_t dest, rgb_t addMe, UINT8 alpha)
{
int r, g, b;
int ir, ig, ib;
r = (int)RGB_RED (dest);
g = (int)RGB_GREEN(dest);
b = (int)RGB_BLUE (dest);
ir = (int)RGB_RED (addMe);
ig = (int)RGB_GREEN(addMe);
ib = (int)RGB_BLUE (addMe);
if (alpha & 4)
{ r -= ir; if (r < 0) r = 0; }
else
{ r += ir; if (r > 255) r = 255; }
if (alpha & 2)
{ g -= ig; if (g < 0) g = 0; }
else
{ g += ig; if (g > 255) g = 255; }
if (alpha & 1)
{ b -= ib; if (b < 0) b = 0; }
else
{ b += ib; if (b > 255) b = 255; }
return MAKE_RGB(r,g,b);
}
void jal_blend_drawgfx(bitmap_t *dest_bmp,const rectangle *clip,const gfx_element *gfx,
UINT32 code,UINT32 color,int flipx,int flipy,int offsx,int offsy,
int transparent_color)
{
if (jal_blend_table == NULL)
{
drawgfx_transpen(dest_bmp,clip,gfx,code,color,flipx,flipy,offsx,offsy,transparent_color);
return;
}
/* Start drawing */
if (gfx)
{
const pen_t *pal = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
const UINT8 *alpha = &jal_blend_table[gfx->color_granularity * (color % gfx->total_colors)];
const UINT8 *source_base = gfx_element_get_data(gfx, code % gfx->total_elements);
int x_index_base, y_index, sx, sy, ex, ey;
int xinc, yinc;
xinc = flipx ? -1 : 1;
yinc = flipy ? -1 : 1;
x_index_base = flipx ? gfx->width-1 : 0;
y_index = flipy ? gfx->height-1 : 0;
/* start coordinates */
sx = offsx;
sy = offsy;
/* end coordinates */
ex = sx + gfx->width;
ey = sy + gfx->height;
if (clip)
{
if (sx < clip->min_x)
{ /* clip left */
int pixels = clip->min_x-sx;
sx += pixels;
x_index_base += xinc*pixels;
}
if (sy < clip->min_y)
{ /* clip top */
int pixels = clip->min_y-sy;
sy += pixels;
y_index += yinc*pixels;
}
/* NS 980211 - fixed incorrect clipping */
if (ex > clip->max_x+1)
{ /* clip right */
ex = clip->max_x+1;
}
if (ey > clip->max_y+1)
{ /* clip bottom */
ey = clip->max_y+1;
}
}
if (ex > sx)
{ /* skip if inner loop doesn't draw anything */
int x, y;
/* 32-bit destination bitmap */
if (dest_bmp->bpp == 32)
{
/* taken from case 7: TRANSPARENCY_ALPHARANGE */
for (y = sy; y < ey; y++)
{
const UINT8 *source = source_base + y_index*gfx->line_modulo;
UINT32 *dest = BITMAP_ADDR32(dest_bmp, y, 0);
int x_index = x_index_base;
for (x = sx; x < ex; x++)
{
int c = source[x_index];
if (c != transparent_color)
{
if (alpha[c] & 8)
{
/* Comp with clamp */
dest[x] = jal_blend_func(dest[x], pal[c], alpha[c]);
}
else
{
/* Skip the costly alpha step altogether */
dest[x] = pal[c];
}
}
x_index += xinc;
}
y_index += yinc;
}
}
/* 16-bit destination bitmap */
else
{
/* taken from case 7: TRANSPARENCY_ALPHARANGE */
for (y = sy; y < ey; y++)
{
const UINT8 *source = source_base + y_index*gfx->line_modulo;
UINT16 *dest = BITMAP_ADDR16(dest_bmp, y, 0);
int x_index = x_index_base;
for (x = sx; x < ex; x++)
{
int c = source[x_index];
if (c != transparent_color)
{
if (alpha[c] & 8)
{
/* Comp with clamp */
dest[x] = jal_blend_func(dest[x], pal[c], alpha[c]);
}
else
{
/* Skip the costly alpha step altogether */
dest[x] = pal[c];
}
}
x_index += xinc;
}
y_index += yinc;
}
}
}
}
}