/* video/spbactn.c - see drivers/spbactn.c for more info */
/* rather similar to galspnbl.c */
#include "driver.h"
extern UINT16 *spbactn_bgvideoram, *spbactn_fgvideoram, *spbactn_spvideoram;
static mame_bitmap *tile_bitmap_bg, *tile_bitmap_fg;
/* mix & blend the paletted 16-bit tile and sprite bitmaps into an RGB 32-bit bitmap */
static void blendbitmaps(running_machine *machine,
mame_bitmap *dest,mame_bitmap *src1,mame_bitmap *src2,
int sx,int sy,const rectangle *clip)
{
int ox;
int oy;
int ex;
int ey;
/* check bounds */
ox = sx;
oy = sy;
ex = sx + src1->width - 1;
if (sx < 0) sx = 0;
if (sx < clip->min_x) sx = clip->min_x;
if (ex >= dest->width) ex = dest->width - 1;
if (ex > clip->max_x) ex = clip->max_x;
if (sx > ex) return;
ey = sy + src1->height - 1;
if (sy < 0) sy = 0;
if (sy < clip->min_y) sy = clip->min_y;
if (ey >= dest->height) ey = dest->height - 1;
if (ey > clip->max_y) ey = clip->max_y;
if (sy > ey) return;
{
const pen_t *paldata = machine->pens;
UINT32 *end;
UINT16 *sd1 = src1->base; /* source data */
UINT16 *sd2 = src2->base;
int sw = ex-sx+1; /* source width */
int sh = ey-sy+1; /* source height */
int sm = src1->rowpixels; /* source modulo */
UINT32 *dd = BITMAP_ADDR32(dest, sy, sx); /* dest data */
int dm = dest->rowpixels; /* dest modulo */
sd1 += (sx-ox);
sd1 += sm * (sy-oy);
sd2 += (sx-ox);
sd2 += sm * (sy-oy);
sm -= sw;
dm -= sw;
while (sh)
{
#define BLENDPIXEL(x) if (sd2[x]) { \
if (sd2[x] & 0x1000) { \
dd[x] = paldata[sd1[x] & 0x07ff] + paldata[sd2[x]]; \
} else { \
dd[x] = paldata[sd2[x]]; \
} \
} else { \
dd[x] = paldata[sd1[x]]; \
}
end = dd + sw;
while (dd <= end - 8)
{
BLENDPIXEL(0);
BLENDPIXEL(1);
BLENDPIXEL(2);
BLENDPIXEL(3);
BLENDPIXEL(4);
BLENDPIXEL(5);
BLENDPIXEL(6);
BLENDPIXEL(7);
dd += 8;
sd1 += 8;
sd2 += 8;
}
while (dd < end)
{
BLENDPIXEL(0);
dd++;
sd1++;
sd2++;
}
sd1 += sm;
sd2 += sm;
dd += dm;
sh--;
#undef BLENDPIXEL
}
}
}
/* from gals pinball (which was in turn from ninja gaiden) */
static int draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect, int priority)
{
static const UINT8 layout[8][8] =
{
{ 0, 1, 4, 5,16,17,20,21},
{ 2, 3, 6, 7,18,19,22,23},
{ 8, 9,12,13,24,25,28,29},
{10,11,14,15,26,27,30,31},
{32,33,36,37,48,49,52,53},
{34,35,38,39,50,51,54,55},
{40,41,44,45,56,57,60,61},
{42,43,46,47,58,59,62,63}
};
int count = 0;
int offs;
for (offs = (0x1000 - 16) / 2; offs >= 0; offs -= 8)
{
int sx, sy, code, color, size, attr, flipx, flipy;
int col, row;
attr = spbactn_spvideoram[offs];
if ((attr & 0x0004) &&
((attr & 0x0030) >> 4) == priority)
{
flipx = attr & 0x0001;
flipy = attr & 0x0002;
code = spbactn_spvideoram[offs + 1];
color = spbactn_spvideoram[offs + 2];
size = 1 << (color & 0x0003); /* 1,2,4,8 */
color = (color & 0x00f0) >> 4;
sx = spbactn_spvideoram[offs + 4];
sy = spbactn_spvideoram[offs + 3];
attr &= ~0x0040; /* !!! */
if (attr & 0x0040)
color |= 0x0180;
else
color |= 0x0080;
for (row = 0; row < size; row++)
{
for (col = 0; col < size; col++)
{
int x = sx + 8 * (flipx ? (size - 1 - col) : col);
int y = sy + 8 * (flipy ? (size - 1 - row) : row);
drawgfx(bitmap, machine->gfx[2],
code + layout[row][col],
color,
flipx, flipy,
x, y,
cliprect, TRANSPARENCY_PEN, 0);
}
}
count++;
}
}
return count;
}
VIDEO_START( spbactn )
{
/* allocate bitmaps */
tile_bitmap_bg = auto_bitmap_alloc(machine->screen[0].width, machine->screen[0].height, BITMAP_FORMAT_INDEXED16);
tile_bitmap_fg = auto_bitmap_alloc(machine->screen[0].width, machine->screen[0].height, BITMAP_FORMAT_INDEXED16);
}
VIDEO_UPDATE( spbactn )
{
int offs, sx, sy;
fillbitmap(tile_bitmap_fg, 0, cliprect);
/* draw table bg gfx */
for (sx = sy = offs = 0; offs < 0x4000 / 2; offs++)
{
int attr, code, colour;
code = spbactn_bgvideoram[offs + 0x4000 / 2];
attr = spbactn_bgvideoram[offs + 0x0000 / 2];
colour = ((attr & 0x00f0) >> 4) | 0x80;
drawgfx(tile_bitmap_bg, machine->gfx[1],
code,
colour,
0, 0,
16 * sx, 8 * sy,
cliprect, TRANSPARENCY_NONE, 0);
sx++;
if (sx > 63)
{
sy++;
sx = 0;
}
}
if (draw_sprites(machine, tile_bitmap_bg, cliprect, 0))
{
/* kludge: draw table bg gfx again if priority 0 sprites are enabled */
for (sx = sy = offs = 0; offs < 0x4000 / 2; offs++)
{
int attr, code, colour;
code = spbactn_bgvideoram[offs + 0x4000 / 2];
attr = spbactn_bgvideoram[offs + 0x0000 / 2];
colour = ((attr & 0x00f0) >> 4) | 0x80;
drawgfx(tile_bitmap_bg, machine->gfx[1],
code,
colour,
0, 0,
16 * sx, 8 * sy,
cliprect, TRANSPARENCY_PEN, 0);
sx++;
if (sx > 63)
{
sy++;
sx = 0;
}
}
}
draw_sprites(machine, tile_bitmap_bg, cliprect, 1);
/* draw table fg gfx */
for (sx = sy = offs = 0; offs < 0x4000 / 2; offs++)
{
int attr, code, colour;
code = spbactn_fgvideoram[offs + 0x4000 / 2];
attr = spbactn_fgvideoram[offs + 0x0000 / 2];
colour = ((attr & 0x00f0) >> 4);
/* blending */
if (attr & 0x0008)
colour += 0x00f0;
else
colour |= 0x0080;
drawgfx(tile_bitmap_fg, machine->gfx[0],
code,
colour,
0, 0,
16 * sx, 8 * sy,
cliprect,TRANSPARENCY_PEN, 0);
sx++;
if (sx > 63)
{
sy++;
sx = 0;
}
}
draw_sprites(machine, tile_bitmap_fg, cliprect, 2);
draw_sprites(machine, tile_bitmap_fg, cliprect, 3);
/* mix & blend the tilemaps and sprites into a 32-bit bitmap */
blendbitmaps(machine, bitmap, tile_bitmap_bg, tile_bitmap_fg, 0, 0, cliprect);
return 0;
}