

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


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

static void init_save_state_multipac(void)
{
	state_save_register_global(charbank);
	state_save_register_global(spritebank);
	state_save_register_global(colourbank);
	state_save_register_global(flipscreen);
	state_save_register_global(bgpriority);
}

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

	SET_TILE_INFO(0,code,attr,0)
}

VIDEO_START( multipac )
{
	init_save_state_multipac();

	charbank = 0;
	spritebank = 0;
	colourbank = 0;
	flipscreen = 0;
	bgpriority = 0;

	/* In the Pac Man based games 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;
}

PALETTE_INIT( multipac )
{
	UINT16 i,i1=0,i2,k,n=128;	/* n = size of one bank of lookup table */
	#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])

	/* convert palette to mame equivalent. "total_colors" is size of MDRV_PALETTE_LENGTH and = size of palette roms */
	/* "color_prom" is a pointer to the start of REGION_PROMS and is used to read each byte from that region */
	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++;
	}

	/* Since lookup table immediately follows palette, color_prom now points to the beginning of the lookup table */
	/* k = bank counter; k << 5 is because each bank is 32 bytes long. TOTAL_COLORS = size of MDRV_COLORTABLE_LENGTH. */
	/* we are converting the lookup codes into the mame colour codes for each screen element */
	for (k = 0;k < (TOTAL_COLORS(0) / n); k++)
	{
		i = i1;
		i2 = i1 + n;		
		for (i = i1;i < i2;i++)
		{
			if (*color_prom & 15)
				COLOR(0,i) = (*color_prom & 15) + (k << 5);
			else
				COLOR(0,i) = 0;    /* preserve transparency */

			color_prom++;
		}
		i1 += n;
	}
}

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[1],
					( spriteram[offs] >> 2 ) | (spritebank << 6),
					( spriteram[offs + 1] & 0x1f ) | (colourbank << 5),
					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[1],
					( spriteram[offs] >> 2 ) | (spritebank << 6),
					( spriteram[offs + 1] & 0x1f ) | (colourbank << 5),
					spriteram[offs] & 1,spriteram[offs] & 2,
					sx - 256,sy,
					&spriteclip,TRANSPARENCY_COLOR,0);
		}
		/* In the Pac Man based games 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[1],
					( spriteram[offs] >> 2 ) | (spritebank << 6),
					( spriteram[offs + 1] & 0x1f ) | (colourbank << 5),
					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[1],
					( spriteram[offs] >> 2 ) | (spritebank << 6),
					( spriteram[offs + 1] & 0x1f ) | (colourbank << 5),
					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;
}


WRITE8_HANDLER( multipac_gfxbank_w )
{
	charbank = data;
	spritebank = data;
}

/* multipac passes bankselect info for the 4a and 7f roms on separate bytes. MAME can only use one of them */
WRITE8_HANDLER( multipac_palbank_w )
{
	if (offset) colourbank = data;
}


/* =============================================
	96in1 / Mad Pac by Robert, July 2007
   ============================================= */


void _96in1b_gfxbank_w ( UINT8 gfxbank )
{
	UINT8 banks[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 7, 4, 2, 3, 5, 6, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 };
	charbank = gfxbank;
	spritebank = gfxbank;
	colourbank = banks[gfxbank];
}

void madpac_gfxbank_w ( UINT8 gfxbank )
{
	charbank = gfxbank;
	spritebank = gfxbank;

	if (gfxbank > 15)
		colourbank = gfxbank - 15;
	else
		colourbank = 0;
}

/* ==============================================
	8in1 / 16in1 by Robert, July 2007
   ============================================== */

void pm8in1_gfxbank_w ( UINT8 gfxbank )
{
	UINT8 banks[] = { 0, 0, 0, 0, 1, 1, 1, 2 };
	charbank = banks[gfxbank];
	spritebank = charbank;
}

void pm12in1_gfxbank_w ( UINT8 gfxbank )
{
	UINT8 banks[] = { 0, 0, 0, 2, 0, 0, 0, 2, 1, 99, 1, 99, 1, 99, 1, 99 };
	charbank = banks[gfxbank];
	spritebank = charbank;
}

/* =============================================================================================
	The following code is not used, but kept for reference purposes
   ============================================================================================= */

#if 0

/* Not needed any more but kept for reference */
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[1],
				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[1],
				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[1],
				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[1],
				spriteram[offs] >> 2,
				spriteram[offs + 1] & 0x1f,
				spriteram[offs] & 2,spriteram[offs] & 1,
				sx - 256,sy + xoffsethack,
				&spritevisiblearea,TRANSPARENCY_COLOR,0);
	}
	return 0;
}
#endif

