// license:BSD-3-Clause
// copyright-holders:Bryan McPhail, David Haywood
#include "emu.h"
#include "includes/boogwing.h"
#include "screen.h"
void boogwing_state::video_start()
{
m_priority = 0;
m_sprgen[0]->alloc_sprite_bitmap();
m_sprgen[1]->alloc_sprite_bitmap();
save_item(NAME(m_priority));
}
/* Mix the 2 sprite planes with the already rendered tilemaps..
note, if we implement tilemap blending etc. too we'll probably have to mix those in here as well..
this is just a reimplementation of the old priority system used before conversion but to work with
the bitmaps. It could probably be simplified / improved greatly, along with the long-standing bugs
fixed, with manual mixing you have full control.
apparently priority is based on a PROM, that should be used if possible.
*/
void boogwing_state::mix_boogwing(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
int y, x;
const pen_t *paldata = &m_deco_ace->pen(0);
bitmap_ind16 *sprite_bitmap1, *sprite_bitmap2;
bitmap_ind8* priority_bitmap;
uint16_t priority = m_priority;
sprite_bitmap1 = &m_sprgen[0]->get_sprite_temp_bitmap();
sprite_bitmap2 = &m_sprgen[1]->get_sprite_temp_bitmap();
priority_bitmap = &screen.priority();
uint32_t* dstline;
uint16_t *srcline1, *srcline2;
uint8_t *srcpriline;
for (y=cliprect.min_y;y<=cliprect.max_y;y++)
{
srcline1=&sprite_bitmap1->pix16(y,0);
srcline2=&sprite_bitmap2->pix16(y,0);
srcpriline=&priority_bitmap->pix8(y,0);
dstline=&bitmap.pix32(y,0);
for (x=cliprect.min_x;x<=cliprect.max_x;x++)
{
uint16_t pix1 = srcline1[x];
uint16_t pix2 = srcline2[x];
/* Here we have
pix1 - raw pixel / colour / priority data from first 1sdt chip
pix2 - raw pixel / colour / priority data from first 2nd chip
*/
int pri1, pri2;
int spri1, spri2, alpha2;
alpha2 = m_deco_ace->get_alpha((pix2 >> 4) & 0xf);
// pix1 sprite vs pix2 sprite
if (pix1 & 0x400) // TODO - check only in pri mode 2??
spri1 = 8;
else
spri1 = 32;
// pix1 sprite vs playfield
switch (priority)
{
case 0x01:
{
if ((pix1 & 0x600))
pri1 = 16;
else
pri1 = 64;
}
break;
default:
{
if ((pix1 & 0x600) == 0x600)
pri1 = 4;
else if ((pix1 & 0x600) == 0x400)
pri1 = 16;
else
pri1 = 64;
}
break;
}
// pix2 sprite vs pix1 sprite
if ((pix2 & 0x600) == 0x600)
spri2 = 4;
else if ((pix2 & 0x600))
spri2 = 16;
else
spri2 = 64;
// Transparency
if (pix2 & 0x100)
alpha2 = 0x80; // TODO : Uses 0x10-0x14 of Aceram?
// alpha2 = m_deco_ace->get_alpha(0x14 + ((pix & 0xf0) > 0x50) ? 0x5 : ((pix2 >> 4) & 0x7)); This fixes explosion effects, but this is HACK.
// pix2 sprite vs playfield
switch (priority)
{
case 0x02:
{
// Additional sprite alpha in this mode
if (pix2 & 0x400)
alpha2 = 0x80; // TODO
// Sprite vs playfield
if ((pix2 & 0x600) == 0x600)
pri2 = 4;
else if ((pix2 & 0x600) == 0x400)
pri2 = 16;
else
pri2 = 64;
}
break;
default:
{
if ((pix2 & 0x400) == 0x400)
pri2 = 16;
else
pri2 = 64;
}
break;
}
uint8_t bgpri = srcpriline[x];
/* once we get here we have
pri1 - 4/16/64 (sprite chip 1 pixel priority relative to bg)
pri2 - 4/16/64 (sprite chip 2 pixel priority relative to bg)
spri1 - 8/32 (priority of sprite chip 1 relative to other sprite chip)
spri2 - 4/16/64 (priority of sprite chip 2 relative to other sprite chip)
alpha2 - 0x80/0xff alpha level of sprite chip 2 pixels (0x80 if enabled, 0xff if not)
bgpri - 0 / 8 / 32 (from drawing tilemaps earlier, to compare above pri1/pri2 priorities against)
pix1 - same as before (ready to extract just colour data from)
pix2 - same as before ^^
*/
int drawnpixe1 = 0;
if (pix1 & 0xf)
{
if (pri1 > bgpri)
{
dstline[x] = paldata[(pix1&0x1ff)+0x500];
drawnpixe1 = 1;
}
}
if (pix2 & 0xf)
{
if (pri2 > bgpri)
{
if ((!drawnpixe1) || (spri2 > spri1))
{
if (alpha2>=0xff)
{
dstline[x] = paldata[(pix2&0xff)+0x700];
}
else
{
uint32_t base = dstline[x];
dstline[x] = alpha_blend_r32(base, paldata[(pix2&0xff)+0x700], alpha2);
}
}
}
}
}
}
}
uint32_t boogwing_state::screen_update_boogwing(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
address_space &space = machine().dummy_space();
uint16_t flip = m_deco_tilegen[0]->pf_control_r(space, 0, 0xffff);
uint16_t priority = m_priority;
// sprites are flipped relative to tilemaps
flip_screen_set(BIT(flip, 7));
m_sprgen[0]->set_flip_screen(!BIT(flip, 7));
m_sprgen[1]->set_flip_screen(!BIT(flip, 7));
/* Draw sprite planes to bitmaps for later mixing */
m_sprgen[1]->draw_sprites(bitmap, cliprect, m_spriteram[1]->buffer(), 0x400);
m_sprgen[0]->draw_sprites(bitmap, cliprect, m_spriteram[0]->buffer(), 0x400);
m_deco_tilegen[0]->pf_update(m_pf_rowscroll[0], m_pf_rowscroll[1]);
m_deco_tilegen[1]->pf_update(m_pf_rowscroll[2], m_pf_rowscroll[3]);
/* Draw playfields */
bitmap.fill(m_deco_ace->pen(0x400), cliprect); /* pen not confirmed */
screen.priority().fill(0);
// bit&0x8 is definitely some kind of palette effect
// bit&0x4 combines playfields
if ((priority & 0x7) == 0x5)
{
m_deco_tilegen[0]->tilemap_2_draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE, 0);
m_deco_tilegen[1]->tilemap_12_combine_draw(screen, bitmap, cliprect, 0, 32);
}
else if ((priority & 0x7) == 0x1 || (priority & 0x7) == 0x2)
{
m_deco_tilegen[1]->tilemap_2_draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE, 0);
m_deco_tilegen[0]->tilemap_2_draw(screen, bitmap, cliprect, 0, 8);
m_deco_tilegen[1]->tilemap_1_draw(screen, bitmap, cliprect, 0, 32);
}
else if ((priority & 0x7) == 0x3)
{
m_deco_tilegen[1]->tilemap_2_draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE, 0);
m_deco_tilegen[0]->tilemap_2_draw(screen, bitmap, cliprect, 0, 8);
// This mode uses playfield 3 to shadow sprites & playfield 2 (instead of
// regular alpha-blending, the destination is inverted). Not yet implemented.
// m_deco_tilegen[1]->tilemap_1_draw(screen, bitmap, cliprect, TILEMAP_DRAW_ALPHA(0x80), 32);
}
else
{
m_deco_tilegen[1]->tilemap_2_draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE, 0);
m_deco_tilegen[1]->tilemap_1_draw(screen, bitmap, cliprect, 0, 8);
m_deco_tilegen[0]->tilemap_2_draw(screen, bitmap, cliprect, 0, 32);
}
mix_boogwing(screen,bitmap,cliprect);
m_deco_tilegen[0]->tilemap_1_draw(screen, bitmap, cliprect, 0, 0);
return 0;
}