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

  invaders.c

	Written by Robbbert in December 2008 for MisfitMAME.


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

#include "driver.h"
#include "invaders.h"


static UINT8 i,x,y,data;
static offs_t offs;
static UINT8 *color_map_base;
static UINT8 fore_color;
static UINT8 color;

static pen_t pens[8];

/*************************************
 *
 *  Video
 *
 *************************************/

static void invaders_get_pens(pen_t *pens)
{
	pens[0] = RGB_BLACK;
	pens[1] = RGB_WHITE;
}

static void invadpt2_get_pens(pen_t *pens)
{
	for (i = 0; i < 8; i++)
		pens[i] = MAKE_RGB(pal1bit(i >> 0), pal1bit(i >> 2), pal1bit(i >> 1));
}


INLINE void set_pixel(bitmap_t *bitmap, UINT8 y, UINT8 x, pen_t *pens, UINT8 color)
{
	if (y >= INVADERS_VCOUNTER_START_NO_VBLANK)
	{
		if (flipscreen)
			*BITMAP_ADDR32(bitmap, INVADERS_VBSTART - 1 - (y - INVADERS_VCOUNTER_START_NO_VBLANK), INVADERS_HPIXCOUNT - 1 - x) = pens[color&0x07];
		else
			*BITMAP_ADDR32(bitmap, y - INVADERS_VCOUNTER_START_NO_VBLANK, x) = pens[color&0x07];
	}
}


INLINE void set_8_pixels(bitmap_t *bitmap, UINT8 y, UINT8 x, UINT8 data, pen_t *pens, UINT8 fore_color, UINT8 back_color)
{
	for (i = 0; i < 8; i++)
	{
		set_pixel(bitmap, y, x|i, pens, (data & 1) ? fore_color : back_color);
		data >>= 1;
	}
}


VIDEO_UPDATE( invaders )
{
	x = 0;
	y = INVADERS_VCOUNTER_START_NO_VBLANK;
	data = 0;

	invaders_get_pens(pens);

	while (1)
	{
		/* plot the current pixel */
		color = data & 1;

		if (flipscreen)
			*BITMAP_ADDR32(bitmap, INVADERS_VBSTART - 1 - (y - INVADERS_VCOUNTER_START_NO_VBLANK), INVADERS_HPIXCOUNT - 1 - x) = pens[color];
		else
			*BITMAP_ADDR32(bitmap, y - INVADERS_VCOUNTER_START_NO_VBLANK, x) = pens[color];

		/* next pixel */
		data >>= 1;
		x++;

		/* end of line? */
		if (!x)
		{
			/* yes, flush out the shift register */
			for (i = 0; i < 4; i++)
			{
				color = data & 1;

				if (flipscreen)
					*BITMAP_ADDR32(bitmap, INVADERS_VBSTART - 1 - (y - INVADERS_VCOUNTER_START_NO_VBLANK), INVADERS_HPIXCOUNT - 1 - (256|i)) = pens[color];
				else
					*BITMAP_ADDR32(bitmap, y - INVADERS_VCOUNTER_START_NO_VBLANK, 256|i) = pens[color];

				data >>= 1;
			}

			/* next row, data is now 0, so the next line will start with 4 blank pixels */
			y++;

			/* end of screen? */
			if (!y) break;
		}
		/* the video RAM is read at every 8 pixels starting with pixel 4 */
		else if ((x & 7) == 0x04)
			data = invaders_ram[(y << 5) | (x >> 3)];
	}

	return 0;
}

VIDEO_UPDATE( invadpt2 )
{
	invadpt2_get_pens(pens);

	color_map_base = &memory_region(screen->machine, "proms")[player ? 0x0400 : 0];

	for (offs = 0; offs < invaders_ram_size; offs++)
	{
		y = offs >> 5;
		x = offs << 3;
		data = invaders_ram[offs];
		fore_color = screen_red ? 1 : color_map_base[(offs >> 8 << 5) | (offs & 0x1f)];

		set_8_pixels(bitmap, y, x, data, pens, fore_color, 0);
	}

	return 0;
}


/* Generic b&w screen aligned the same as the colour screens */
VIDEO_UPDATE( invbw )
{
	invaders_get_pens(pens);

	for (offs = 0; offs < invaders_ram_size; offs++)
	{
		y = offs >> 5;
		x = offs << 3;
		data = invaders_ram[offs];

		set_8_pixels(bitmap, y, x, data, pens, 1, 0);
	}

	return 0;
}


VIDEO_UPDATE( beaminv )
{
	invaders_get_pens(pens);

	for (offs = 0; offs < invaders_ram_size; offs++)
	{
		y = offs;
		x = offs >> 8 << 3;
		data = invaders_ram[offs];

		for (i = 0; i < 8; i++)
		{
			*BITMAP_ADDR32(bitmap, y, x|i) = pens[data & 1];
			data >>= 1;
		}
	}

	return 0;
}


VIDEO_UPDATE( rollingc )
{
	invadpt2_get_pens(pens);

	for (offs = 0; offs < invaders_ram_size; offs++)
	{
		y = offs >> 5;
		x = offs << 3;
		data = invaders_ram[offs];
		fore_color = invaders_colorram[offs & 0x1f1f];

		set_8_pixels(bitmap, y, x, data, pens, fore_color, 0);
	}

	return 0;
}


VIDEO_UPDATE( rotaryf )
{
	invaders_get_pens(pens);

	for (offs = 0; offs < invaders_ram_size; offs++)
	{
		x = offs << 3;
		y = offs >> 5;
		data = invaders_ram[offs];

		for (i = 0; i < 8; i++)
		{
			if (flipscreen)
				*BITMAP_ADDR32(bitmap, 256-y, 247-(x|i)) = pens[data & 1];
			else
				*BITMAP_ADDR32(bitmap, y, x|i) = pens[data & 1];

			data >>= 1;
		}
	}

	return 0;
}


VIDEO_UPDATE( shuttlei )
{
	invaders_get_pens(pens);

	for (offs = 0; offs < invaders_ram_size; offs++)
	{
		y = offs >> 5;
		x = offs << 3;
		data = invaders_ram[offs];

		for (i = 0; i < 8; i++)
		{
			if (flipscreen)
				*BITMAP_ADDR32(bitmap, 223-y, 256-(x|i)) = (data & 0x80) ? pens[1] : pens[0];
			else
				*BITMAP_ADDR32(bitmap, y+32, x|i) = (data & 0x80) ? pens[1] : pens[0];
			data <<= 1;
		}
	}

	return 0;
}


VIDEO_UPDATE( sstrangr )
{
	invaders_get_pens(pens);

	for (offs = 0; offs < invaders_ram_size; offs++)
	{
		x = offs << 3;
		y = offs >> 5;
		data = invaders_ram[offs];

		for (i = 0; i < 8; i++)
		{
			if (flipscreen)
			{
				*BITMAP_ADDR32(bitmap, y, (x|i)+8) = (data & 0x80) ? pens[1] : pens[0];
				data <<= 1;
			}
			else
			{
				*BITMAP_ADDR32(bitmap, y, x|i) = pens[data & 1];
				data >>= 1;
			}

		}
	}

	return 0;
}


VIDEO_UPDATE( sstrngr2 )
{
	invadpt2_get_pens(pens);

	color_map_base = &memory_region(screen->machine, "proms")[player ? 0x0000 : 0x0200];

	for (offs = 0; offs < invaders_ram_size; offs++)
	{
		y = offs >> 5;
		x = offs << 3;
		data = invaders_ram[offs];
		fore_color = screen_red ? 1 :color_map_base[(offs >> 9 << 5) | (offs & 0x1f)];

		for (i = 0; i < 8; i++)
		{
			if (flipscreen)
			{
				color = (data & 0x80) ? fore_color : 0;
				data <<= 1;
				*BITMAP_ADDR32(bitmap, y, (x|i)+8) = pens[color&0x07];
			}
			else
			{
				color = (data & 0x01) ? fore_color : 0;
				data >>= 1;
				*BITMAP_ADDR32(bitmap, y, x|i) = pens[color&0x07];
			}

		}
	}

	return 0;
}
