/***************************************************************************

   Desert Assault Video emulation - Bryan McPhail, mish@tendril.co.uk

****************************************************************************/

#include "emu.h"
#include "video/deco16ic.h"
#include "includes/dassault.h"
#include "video/decocomn.h"

/******************************************************************************/

static void draw_sprites( running_machine& machine, bitmap_t *bitmap, const rectangle *cliprect, int pf_priority )
{
	dassault_state *state = machine.driver_data<dassault_state>();
	UINT16 *buffered_spriteram = machine.generic.buffered_spriteram.u16;
	int x, y, sprite, colour, multi, fx, fy, inc, flash, mult;
	int offs, bank, gfxbank;
	const UINT16 *spritebase;

	/* Have to loop over the two sprite sources */
	for (bank = 0; bank < 2; bank++)
	{
		for (offs = 0x800 - 4; offs >= 0; offs -= 4)
		{
			int alpha = 0xff, pmask = 0;

			/* Draw the main spritebank after the other one */
			if (bank == 0)
			{
				spritebase = buffered_spriteram;
				gfxbank = 3;
			}
			else
			{
				spritebase = machine.generic.buffered_spriteram2.u16;
				gfxbank = 4;
			}

			sprite = spritebase[offs + 1] & 0x7fff;
			if (!sprite)
				continue;

			x = spritebase[offs + 2];

			/* Alpha on chip 2 only */
			if (bank == 1 && x & 0xc000)
				alpha = 0x80;

			y = spritebase[offs];
			flash = y & 0x1000;
			if (flash && (machine.primary_screen->frame_number() & 1))
				continue;
			colour = (x >> 9) & 0x1f;
			if (y & 0x8000)
				colour += 32;

			fx = y & 0x2000;
			fy = y & 0x4000;
			multi = (1 << ((y & 0x0600) >> 9)) - 1;	/* 1x, 2x, 4x, 8x height */

			x = x & 0x01ff;
			y = y & 0x01ff;
			if (x >= 320) x -= 512;
			if (y >= 256) y -= 512;
			x = 304 - x;
			y = 240 - y;

			if (x > 320)
				continue; /* Speedup */

			sprite &= ~multi;
			if (fy)
				inc = -1;
			else
			{
				sprite += multi;
				inc = 1;
			}

			if (flip_screen_get(machine))
			{
				y = 240 - y;
				x = 304 - x;
				if (fx) fx = 0; else fx = 1;
				if (fy) fy = 0; else fy = 1;
				mult = 16;
			}
			else mult = -16;

			/* Priority */
			switch (pf_priority & 3)
			{
			case 0:
				if (bank == 0)
				{
					switch (spritebase[offs+2]&0xc000)
					{
					case 0xc000: pmask = 1; break;
					case 0x8000: pmask = 8; break;
					case 0x4000: pmask = 32; break;
					case 0x0000: pmask = 128; break;
					}
				}
				else
				{
					if (spritebase[offs + 2] & 0x8000)
						pmask = 64; /* Check */
					else
						pmask = 64;
				}
				break;

			case 1:
				if (bank == 0)
				{
					switch (spritebase[offs + 2] & 0xc000)
					{
					case 0xc000: pmask = 1; break;
					case 0x8000: pmask = 8; break;
					case 0x4000: pmask = 32; break;
					case 0x0000: pmask = 128; break;
					}
				}
				else
				{
					if (spritebase[offs + 2] & 0x8000)
						pmask = 16; /* Check */
					else
						pmask = 16;
				}
				break;

			case 2: /* Unused */
			case 3:
				if (bank == 0)
				{
					switch (spritebase[offs + 2] & 0xc000)
					{
					case 0xc000: pmask = 1; break;
					case 0x8000: pmask = 8; break;
					case 0x4000: pmask = 32; break;
					case 0x0000: pmask = 128; break;
					}
				}
				else
				{
					if (spritebase[offs + 2] & 0x8000)
						pmask = 64; /* Check */
					else
						pmask = 64;
				}
				break;
			}

			while (multi >= 0)
			{
				decocomn_pdrawgfx(
						state->m_decocomn,
						bitmap,cliprect,machine.gfx[gfxbank],
						sprite - multi * inc,
						colour,
						fx, fy,
						x, y + mult * multi,
						0, pmask, 1 << bank, 1, alpha);

				multi--;
			}
		}
	}
}

/******************************************************************************/

SCREEN_UPDATE( dassault )
{
	dassault_state *state = screen->machine().driver_data<dassault_state>();
	UINT16 flip = deco16ic_pf_control_r(state->m_deco_tilegen1, 0, 0xffff);
	UINT16 priority = decocomn_priority_r(state->m_decocomn, 0, 0xffff);

	/* Update tilemaps */
	flip_screen_set(screen->machine(), BIT(flip, 7));
	deco16ic_pf_update(state->m_deco_tilegen1, 0, state->m_pf2_rowscroll);
	deco16ic_pf_update(state->m_deco_tilegen2, 0, state->m_pf4_rowscroll);

	/* Draw playfields/update priority bitmap */
	decocomn_clear_sprite_priority_bitmap(state->m_decocomn);
	bitmap_fill(screen->machine().priority_bitmap, cliprect, 0);
	bitmap_fill(bitmap, cliprect, screen->machine().pens[3072]);
	deco16ic_tilemap_2_draw(state->m_deco_tilegen2, bitmap, cliprect, TILEMAP_DRAW_OPAQUE, 0);

	/* The middle playfields can be swapped priority-wise */
	if ((priority & 3) == 0)
	{
		deco16ic_tilemap_2_draw(state->m_deco_tilegen1, bitmap, cliprect, 0, 2);
		deco16ic_tilemap_1_draw(state->m_deco_tilegen2, bitmap, cliprect, 0, 16);
	}
	else if ((priority & 3) == 1)
	{
		deco16ic_tilemap_1_draw(state->m_deco_tilegen2, bitmap, cliprect, 0, 2);
		deco16ic_tilemap_2_draw(state->m_deco_tilegen1, bitmap, cliprect, 0, 64);
	}
	else if ((priority & 3) == 3)
	{
		deco16ic_tilemap_1_draw(state->m_deco_tilegen2, bitmap, cliprect, 0, 2);
		deco16ic_tilemap_2_draw(state->m_deco_tilegen1, bitmap, cliprect, 0, 16);
	}
	else
	{
		/* Unused */
	}

	/* Draw sprites - two sprite generators, with selectable priority */
	draw_sprites(screen->machine(), bitmap, cliprect, priority);
	deco16ic_tilemap_1_draw(state->m_deco_tilegen1, bitmap, cliprect, 0, 0);
	return 0;
}
