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

  vidhrdw.c

  Functions to emulate the video hardware of the machine.

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

#include "driver.h"
#include "vidhrdw/generic.h"



data8_t *cop01_bgvideoram,*cop01_fgvideoram;

static unsigned char mightguy_vreg[4];
static struct tilemap *bg_tilemap,*fg_tilemap;



PALETTE_INIT( cop01 )
{
	int i;
	#define TOTAL_COLORS(gfxn) (Machine->gfx[gfxn]->total_colors * Machine->gfx[gfxn]->color_granularity)
	#define COLOR(gfxn,offs) (colortable[Machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs])

	for (i = 0;i < Machine->drv->total_colors;i++)
	{
		int bit0,bit1,bit2,bit3,r,g,b;

		bit0 = (color_prom[0] >> 0) & 0x01;
		bit1 = (color_prom[0] >> 1) & 0x01;
		bit2 = (color_prom[0] >> 2) & 0x01;
		bit3 = (color_prom[0] >> 3) & 0x01;
		r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
		bit0 = (color_prom[Machine->drv->total_colors] >> 0) & 0x01;
		bit1 = (color_prom[Machine->drv->total_colors] >> 1) & 0x01;
		bit2 = (color_prom[Machine->drv->total_colors] >> 2) & 0x01;
		bit3 = (color_prom[Machine->drv->total_colors] >> 3) & 0x01;
		g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
		bit0 = (color_prom[2*Machine->drv->total_colors] >> 0) & 0x01;
		bit1 = (color_prom[2*Machine->drv->total_colors] >> 1) & 0x01;
		bit2 = (color_prom[2*Machine->drv->total_colors] >> 2) & 0x01;
		bit3 = (color_prom[2*Machine->drv->total_colors] >> 3) & 0x01;
		b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;

		palette_set_color(i,r,g,b);
		color_prom++;
	}

	color_prom += 2*Machine->drv->total_colors;
	/* color_prom now points to the beginning of the lookup tables */

	/* characters use colors 0-15 (or 0-127, but the eight rows are identical) */
	for (i = 0;i < TOTAL_COLORS(0);i++)
		COLOR(0,i) = i;

	/* background tiles use colors 192-255 */
	/* I don't know how much of the lookup table PROM is hooked up, */
	/* I'm only using the first 32 bytes because the rest is empty. */
	for (i = 0;i < TOTAL_COLORS(1);i++)
		COLOR(1,i) = 0xc0 + (i & 0x30) + (color_prom[((i & 0x40) >> 2) + (i & 0x0f)] & 0x0f);
	color_prom += 256;

	/* sprites use colors 128-143 (or 128-191, but the four rows are identical) */
	for (i = 0;i < TOTAL_COLORS(2);i++)
		COLOR(2,i) = 0x80 + (*(color_prom++) & 0x0f);
}



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

  Callbacks for the TileMap code

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

static void get_bg_tile_info(int tile_index)
{
	int tile = cop01_bgvideoram[tile_index];
	int attr = cop01_bgvideoram[tile_index+0x800];
	int pri  = (attr & 0x80) >> 7;

	/* kludge: priority is not actually pen based, but color based. Since the
	 * game uses a lookup table, the two are not the same thing.
	 * Palette entries with bits 2&3 set have priority over sprites.
	 * tilemap.c can't handle that yet, so I'm cheating, because I know that
	 * color codes using the second row of the lookup table don't use palette
	 * entries 12-15.
	 * The only place where this has any effect is the beach at the bottom of
	 * the screen right at the beginning of mightguy. cop01 doesn't seem to
	 * use priority at all.
	 */
	if (attr & 0x10) pri = 0;

	SET_TILE_INFO(1,tile + ((attr & 0x03) << 8),(attr & 0x1c) >> 2,TILE_SPLIT(pri));
}

static void get_fg_tile_info(int tile_index)
{
	int tile = cop01_fgvideoram[tile_index];
	SET_TILE_INFO(0,tile,0,0);
}



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

  Start the video hardware emulation.

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

VIDEO_START( cop01 )
{
	bg_tilemap = tilemap_create(get_bg_tile_info,tilemap_scan_rows,TILEMAP_SPLIT,      8,8,64,32);
	fg_tilemap = tilemap_create(get_fg_tile_info,tilemap_scan_rows,TILEMAP_TRANSPARENT,8,8,32,32);

	if (!bg_tilemap || !fg_tilemap)
		return 1;

	tilemap_set_transparent_pen(fg_tilemap,15);

	/* priority doesn't exactly work this way, see above */
	tilemap_set_transmask(bg_tilemap,0,0xffff,0x0000); /* split type 0 is totally transparent in front half */
	tilemap_set_transmask(bg_tilemap,1,0x0fff,0xf000); /* split type 1 has pens 0-11 transparent in front half */

	return 0;
}



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

  Memory handlers

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

WRITE_HANDLER( cop01_background_w )
{
	if (cop01_bgvideoram[offset] != data)
	{
		cop01_bgvideoram[offset] = data;
		tilemap_mark_tile_dirty(bg_tilemap,offset & 0x7ff);
	}
}

WRITE_HANDLER( cop01_foreground_w )
{
	if (cop01_fgvideoram[offset] != data)
	{
		cop01_fgvideoram[offset] = data;
		tilemap_mark_tile_dirty(fg_tilemap,offset);
	}
}

WRITE_HANDLER( cop01_vreg_w )
{
	/*	0x40: --xx---- sprite bank, coin counters, flip screen
	 *	      -----x-- flip screen
	 *	      ------xx coin counters
	 *	0x41: xxxxxxxx xscroll
	 *	0x42: ---xx--- ? matches the bg tile color most of the time, but not
	 *                 during level transitions. Maybe sprite palette bank?
	 *                 (the four banks in the PROM are identical)
	 *	      ------x- unused (xscroll overflow)
	 *	      -------x msb xscroll
	 *	0x43: xxxxxxxx yscroll
	 */
	mightguy_vreg[offset] = data;

	if (offset == 0)
	{
		coin_counter_w(0,data & 1);
		coin_counter_w(1,data & 2);
		flip_screen_set(data & 4);
	}
}



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

  Display refresh

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

static void draw_sprites( struct mame_bitmap *bitmap, const struct rectangle *cliprect )
{
	int offs,code,attr,sx,sy,flipx,flipy,color;

	for (offs = 0;offs < spriteram_size;offs += 4)
	{
		code = spriteram[offs+1];
		attr = spriteram[offs+2];
		/* xxxx----	color
		 * ----xx--	flipy,flipx
		 * -------x msbx
		 */
		color = attr>>4;
		flipx = attr & 0x04;
		flipy = attr & 0x08;

		sx = (spriteram[offs+3] - 0x80) + 256 * (attr & 0x01);
		sy = 240 - spriteram[offs];

		if (flip_screen)
		{
			sx = 240 - sx;
			sy = 240 - sy;
			flipx = !flipx;
			flipy = !flipy;
		}

		if (code&0x80)
			code += (mightguy_vreg[0]&0x30)<<3;

		drawgfx(bitmap,Machine->gfx[2],
			code,
			color,
			flipx,flipy,
			sx,sy,
			cliprect,TRANSPARENCY_PEN,0 );
	}
}


VIDEO_UPDATE( cop01 )
{
	tilemap_set_scrollx(bg_tilemap,0,mightguy_vreg[1] + 256 * (mightguy_vreg[2] & 1));
	tilemap_set_scrolly(bg_tilemap,0,mightguy_vreg[3]);

	tilemap_draw(bitmap,cliprect,bg_tilemap,TILEMAP_BACK,0);
	draw_sprites(bitmap,cliprect);
	tilemap_draw(bitmap,cliprect,bg_tilemap,TILEMAP_FRONT,0);
	tilemap_draw(bitmap,cliprect,fg_tilemap,0,0 );
}
