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

    Namco Pac Man

**************************************************************************

    This file is used by the Pac Man, Pengo & Jr Pac Man drivers.

    Pengo & Pac Man are almost identical, the only differences being the
    extra gfx bank in Pengo, and the need to compensate for an hardware
    sprite positioning "bug" in Pac Man.

    Jr Pac Man has the same sprite hardware as Pac Man, the extra bank
    from Pengo and a scrolling playfield at the expense of one color per row
    for the playfield so it can fit in the same amount of ram.

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

#include "driver.h"
#include "includes/pacman.h"
#include "video/pacman.c"
static tilemap *bg_tilemap;
static UINT8 charbank;
static UINT8 spritebank;
static UINT8 palettebank;
static UINT8 colortablebank;
static UINT8 flipscreen;
static UINT8 bgpriority;
static UINT8 gfx_bank;
static int xoffsethack;


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

  Start the video hardware emulation.

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

static void init_save_state_multipac(void)
{
	state_save_register_global(charbank);
	state_save_register_global(spritebank);
	state_save_register_global(palettebank);
	state_save_register_global(colortablebank);
	state_save_register_global(flipscreen);
	state_save_register_global(bgpriority);
	state_save_register_global(gfx_bank);
}

static void multipac_get_tile_info(int tile_index)
{
	int code = videoram[tile_index] | (charbank << 8);
	int attr = (colorram[tile_index] & 0x1f) | (colortablebank << 5) | (palettebank << 6 );

	SET_TILE_INFO(0,code,attr,0)
}

VIDEO_START( multipac )
{
	init_save_state_multipac();

	charbank = 0;
	spritebank = 0;
	palettebank = 0;
	colortablebank = 0;
	flipscreen = 0;
	bgpriority = 0;
	gfx_bank = 1;

	/* In the Pac Man based games (NOT Pengo) the first two sprites must be offset */
	/* one pixel to the left to get a more correct placement */
	xoffsethack = 1;

	bg_tilemap = tilemap_create( multipac_get_tile_info, pacman_scan_rows, TILEMAP_OPAQUE, 8, 8, 36, 28 );

	tilemap_set_scrolldx( bg_tilemap, 0, 384 - 288 );
	tilemap_set_scrolldy( bg_tilemap, 0, 264 - 224 );

	return 0;
}

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

  Draw the game screen in the given mame_bitmap.

***************************************************************************/
VIDEO_UPDATE( multipac )
{
	if (bgpriority != 0)
		fillbitmap(bitmap,Machine->pens[0],&Machine->screen[0].visarea);
	else
		tilemap_draw(bitmap,cliprect,bg_tilemap,TILEMAP_IGNORE_TRANSPARENCY,0);

	if( spriteram_size )
	{
		int offs;

		rectangle spriteclip = spritevisiblearea;
		sect_rect(&spriteclip, cliprect);

		/* Draw the sprites. Note that it is important to draw them exactly in this */
		/* order, to have the correct priorities. */
		for (offs = spriteram_size - 2;offs > 2*2;offs -= 2)
		{
			int sx,sy;

			sx = 272 - spriteram_2[offs + 1];
			sy = spriteram_2[offs] - 31;

			drawgfx(bitmap,Machine->gfx[gfx_bank],
					( spriteram[offs] >> 2 ) | (spritebank << 6),
					( spriteram[offs + 1] & 0x1f ) | (colortablebank << 5) | (palettebank << 6 ),
					spriteram[offs] & 1,spriteram[offs] & 2,
					sx,sy,
					&spriteclip,TRANSPARENCY_COLOR,0);

			/* also plot the sprite with wraparound (tunnel in Crush Roller) */
			drawgfx(bitmap,Machine->gfx[gfx_bank],
					( spriteram[offs] >> 2 ) | (spritebank << 6),
					( spriteram[offs + 1] & 0x1f ) | (colortablebank << 5) | (palettebank << 6 ),
					spriteram[offs] & 1,spriteram[offs] & 2,
					sx - 256,sy,
					&spriteclip,TRANSPARENCY_COLOR,0);
		}
		/* In the Pac Man based games (NOT Pengo) the first two sprites must be offset */
		/* one pixel to the left to get a more correct placement */
		for (offs = 2*2;offs >= 0;offs -= 2)
		{
			int sx,sy;

			sx = 272 - spriteram_2[offs + 1];
			sy = spriteram_2[offs] - 31;

			drawgfx(bitmap,Machine->gfx[gfx_bank],
					( spriteram[offs] >> 2 ) | (spritebank << 6),
					( spriteram[offs + 1] & 0x1f ) | (colortablebank << 5) | (palettebank << 6 ),
					spriteram[offs] & 1,spriteram[offs] & 2,
					sx,sy + xoffsethack,
					&spriteclip,TRANSPARENCY_COLOR,0);

			/* also plot the sprite with wraparound (tunnel in Crush Roller) */
			drawgfx(bitmap,Machine->gfx[gfx_bank],
					( spriteram[offs] >> 2 ) | (spritebank << 6),
					( spriteram[offs + 1] & 0x1f ) | (colortablebank << 5) | (palettebank << 6 ),
					spriteram[offs] & 2,spriteram[offs] & 1,
					sx - 256,sy + xoffsethack,
					&spriteclip,TRANSPARENCY_COLOR,0);
		}
	}

	if (bgpriority != 0)
		tilemap_draw(bitmap,cliprect,bg_tilemap,0,0);
	return 0;
}


/************************************************************************
  MULTIPAC adapted for MAME by Robert, Feb 2007
 ************************************************************************/

PALETTE_INIT( multipac )
{
	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,r,g,b;


		/* red component */
		bit0 = (*color_prom >> 0) & 0x01;
		bit1 = (*color_prom >> 1) & 0x01;
		bit2 = (*color_prom >> 2) & 0x01;
		r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
		/* green component */
		bit0 = (*color_prom >> 3) & 0x01;
		bit1 = (*color_prom >> 4) & 0x01;
		bit2 = (*color_prom >> 5) & 0x01;
		g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
		/* blue component */
		bit0 = 0;
		bit1 = (*color_prom >> 6) & 0x01;
		bit2 = (*color_prom >> 7) & 0x01;
		b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;

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

	/* color_prom now points to the beginning of the lookup table */

	/* character lookup table */
	/* sprites use the same color lookup table as characters */
	for (i = 0;i < TOTAL_COLORS(0);i++)
		COLOR(0,i) = *(color_prom++) & 0x0f;

	color_prom += 0x80;

	/* second bank character lookup table - pacman plus */
	for (i = 0;i < TOTAL_COLORS(6);i++)
	{
		if (*color_prom &0x0f)
			COLOR(6,i) = (*color_prom & 0x0f) + 0x10;
		else
			COLOR(6,i) = 0;    /* preserve transparency */

		color_prom++;
	}

	color_prom += 0x80;

	/* third bank character lookup table - crush roller */
	for (i = 0;i < TOTAL_COLORS(0x1a);i++)
	{
		if (*color_prom)
			COLOR(0x1a,i) = (*color_prom & 0x0f) + 0x00;
		else
			COLOR(0x1a,i) = 0;    /* preserve transparency */

		color_prom++;
	}

	color_prom += 0x80;

	/* fourth bank character lookup table - lizard wizard */
        for (i = 0;i < TOTAL_COLORS(0x1c);i++)
	{
		if (*color_prom)
			COLOR(0x1c,i) = (*color_prom & 0x0f) + 0x30;
		else
			COLOR(0x1c,i) = 0;    /* preserve transparency */

		color_prom++;
	}
}

WRITE8_HANDLER( multipac_gfxbank_w )
{
	charbank = data << 1;
	gfx_bank = charbank + 1;
}

WRITE8_HANDLER( multipac_tilecolor_w )
{
	colortablebank = data;
}


/************************************************************************
  SUPERABC adapted for MAME by Robert, Mar 2007
 ************************************************************************/

VIDEO_UPDATE( superabc )
{
	int offs;

	for (offs = videoram_size - 1; offs > 0; offs--)
	{
		{
			int mx,my,sx,sy;

			mx = offs % 32;
			my = offs / 32;

			if (my < 2)
			{
				if (mx < 2 || mx >= 30) continue; /* not visible */
				sx = my + 34;
				sy = mx - 2;
			}
			else if (my >= 30)
			{
				if (mx < 2 || mx >= 30) continue; /* not visible */
				sx = my - 30;
				sy = mx - 2;
			}
			else
			{
				sx = mx + 2;
				sy = my - 2;
			}

			if (flipscreen)
			{
				sx = 35 - sx;
				sy = 27 - sy;
			}

			drawgfx(bitmap,Machine->gfx[charbank],
					videoram[offs],
					colorram[offs] & 0x1f,
					flipscreen,flipscreen,
					sx*8,sy*8,
					&Machine->screen[0].visarea,TRANSPARENCY_NONE,0);
		}
	}


	/* Draw the sprites. Note that it is important to draw them exactly in this */
	/* order, to have the correct priorities. */
	for (offs = spriteram_size - 2;offs > 2*2;offs -= 2)
	{
		int sx,sy;

		sx = 272 - spriteram_2[offs + 1];
		sy = spriteram_2[offs] - 31;

		drawgfx(bitmap,Machine->gfx[gfx_bank],
				spriteram[offs] >> 2,
				spriteram[offs + 1] & 0x1f,
				spriteram[offs] & 1,spriteram[offs] & 2,
				sx,sy,
				&spritevisiblearea,TRANSPARENCY_COLOR,0);

	/* also plot the sprite with wraparound (tunnel in Crush Roller) */
		drawgfx(bitmap,Machine->gfx[gfx_bank],
				spriteram[offs] >> 2,
				spriteram[offs + 1] & 0x1f,
				spriteram[offs] & 1,spriteram[offs] & 2,
				sx - 256,sy,
				&spritevisiblearea,TRANSPARENCY_COLOR,0);
	}
	/* In the Pac Man based games (NOT Pengo) the first two sprites must be offset */
	/* one pixel to the left to get a more correct placement */
	for (offs = 2*2;offs >= 0;offs -= 2)
	{
		int sx,sy;


		sx = 272 - spriteram_2[offs + 1];
		sy = spriteram_2[offs] - 31;

		drawgfx(bitmap,Machine->gfx[gfx_bank],
				spriteram[offs] >> 2,
				spriteram[offs + 1] & 0x1f,
				spriteram[offs] & 1,spriteram[offs] & 2,
				sx,sy + xoffsethack,
				&spritevisiblearea,TRANSPARENCY_COLOR,0);

		/* also plot the sprite with wraparound (tunnel in Crush Roller) */
		drawgfx(bitmap,Machine->gfx[gfx_bank],
				spriteram[offs] >> 2,
				spriteram[offs + 1] & 0x1f,
				spriteram[offs] & 2,spriteram[offs] & 1,
				sx - 256,sy + xoffsethack,
				&spritevisiblearea,TRANSPARENCY_COLOR,0);
	}
	return 0;
}
