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

	Video Hardware for Nichibutsu Mahjong series.

	Driver by Takahiro Nogi 2000/06/07 -

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

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


static int pastelgl_drawx, pastelgl_drawy;
static int pastelgl_sizex, pastelgl_sizey;
static int pastelgl_radrx, pastelgl_radry;
static int pastelgl_gfxrom;
static int pastelgl_dispflag;
static int pastelgl_gfxflag;
static int pastelgl_flipscreen;
static int pastelgl_flipx, pastelgl_flipy;
static int pastelgl_screen_refresh;
static int pastelgl_palbank;

static struct mame_bitmap *pastelgl_tmpbitmap;
static unsigned char *pastelgl_videoram;
static unsigned char *pastelgl_paltbl;


void pastelgl_vramflip(void);
void pastelgl_gfxdraw(void);


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


******************************************************************************/
PALETTE_INIT( pastelgl )
{
	int i;

	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[0] >> 4) & 0x01;
		bit1 = (color_prom[0] >> 5) & 0x01;
		bit2 = (color_prom[0] >> 6) & 0x01;
		bit3 = (color_prom[0] >> 7) & 0x01;
		g = 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;
		b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;

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

void pastelgl_paltbl_w(int offset, int data)
{
	pastelgl_paltbl[offset] = data;
}

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


******************************************************************************/
void pastelgl_radrx_w(int data)
{
	pastelgl_radrx = data;
}

void pastelgl_radry_w(int data)
{
	pastelgl_radry = data;
}

void pastelgl_sizex_w(int data)
{
	pastelgl_sizex = data;
}

void pastelgl_sizey_w(int data)
{
	pastelgl_sizey = data;

	pastelgl_gfxdraw();
}

void pastelgl_drawx_w(int data)
{
	pastelgl_drawx = (data ^ 0xff);
}

void pastelgl_drawy_w(int data)
{
	pastelgl_drawy = (data ^ 0xff);
}

void pastelgl_dispflag_w(int data)
{
	static int pastelgl_flipscreen_old = -1;

	pastelgl_gfxflag = data;

	pastelgl_flipx = (data & 0x01) ? 1 : 0;
	pastelgl_flipy = (data & 0x02) ? 1 : 0;
	pastelgl_flipscreen = (data & 0x04) ? 0 : 1;
	pastelgl_dispflag = (data & 0x08) ? 0 : 1;		// unused ?
//	if (data & 0xf0) usrintf_showmessage("Unknown GFXFLAG!! (%02X)", (data & 0xf0));

	if (nb1413m3_type == NB1413M3_PASTELGL)
	{
		pastelgl_flipscreen ^= 1;
	}

	if (pastelgl_flipscreen != pastelgl_flipscreen_old)
	{
		pastelgl_vramflip();
		pastelgl_screen_refresh = 1;
		pastelgl_flipscreen_old = pastelgl_flipscreen;
	}
}

void pastelgl_romsel_w(int data)
{
	pastelgl_gfxrom = ((data & 0xc0) >> 6);
	pastelgl_palbank = ((data & 0x10) >> 4);

	if ((pastelgl_gfxrom << 16) > (memory_region_length(REGION_GFX1) - 1))
	{
#ifdef MAME_DEBUG
		usrintf_showmessage("GFXROM BANK OVER!!");
#endif
		pastelgl_gfxrom = 0;
	}
}

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


******************************************************************************/
void pastelgl_vramflip(void)
{
	int x, y;
	unsigned char color1, color2;

	for (y = 0; y < Machine->drv->screen_height; y++)
	{
		for (x = 0; x < Machine->drv->screen_width; x++)
		{
			color1 = pastelgl_videoram[(y * Machine->drv->screen_width) + x];
			color2 = pastelgl_videoram[((y ^ 0xff) * Machine->drv->screen_width) + (x ^ 0xff)];
			pastelgl_videoram[(y * Machine->drv->screen_width) + x] = color2;
			pastelgl_videoram[((y ^ 0xff) * Machine->drv->screen_width) + (x ^ 0xff)] = color1;
		}
	}
}

void pastelgl_gfxdraw(void)
{
	unsigned char *GFX = memory_region(REGION_GFX1);

	int x, y;
	int dx, dy;
	int startx, starty;
	int sizex, sizey;
	int skipx, skipy;
	int ctrx, ctry;
	int readflag;
	int tflag;
	int gfxaddr;
	unsigned char color;
	unsigned char drawcolor;

	if (pastelgl_flipx)
	{
		pastelgl_drawx -= (pastelgl_sizex << 1);
		startx = pastelgl_sizex;
		sizex = ((pastelgl_sizex ^ 0xff) + 1);
		skipx = -1;
	}
	else
	{
		pastelgl_drawx = (pastelgl_drawx - pastelgl_sizex);
		startx = 0;
		sizex = (pastelgl_sizex + 1);
		skipx = 1;
	}

	if (pastelgl_flipy)
	{
		pastelgl_drawy -= (pastelgl_sizey << 1);
		starty = pastelgl_sizey;
		sizey = ((pastelgl_sizey ^ 0xff) + 1);
		skipy = -1;
	}
	else
	{
		pastelgl_drawy = (pastelgl_drawy - pastelgl_sizey);
		starty = 0;
		sizey = (pastelgl_sizey + 1);
		skipy = 1;
	}

	gfxaddr = ((pastelgl_gfxrom << 16) + (pastelgl_radry << 8) + pastelgl_radrx);

	readflag = 0;

	for (y = starty, ctry = sizey; ctry > 0; y += skipy, ctry--)
	{
		for (x = startx, ctrx = sizex; ctrx > 0; x += skipx, ctrx--)
		{
			if ((gfxaddr > (memory_region_length(REGION_GFX1) - 1)))
			{
#ifdef MAME_DEBUG
				usrintf_showmessage("GFXROM ADDRESS OVER!!");
#endif
				gfxaddr = 0;
			}

			color = GFX[gfxaddr];

			if (pastelgl_flipscreen)
			{
				dx = (((pastelgl_drawx + x) ^ 0xff) & 0xff);
				dy = (((pastelgl_drawy + y) ^ 0xff) & 0xff);
			}
			else
			{
				dx = ((pastelgl_drawx + x) & 0xff);
				dy = ((pastelgl_drawy + y) & 0xff);
			}

			if (!readflag)
			{
				// 1st, 3rd, 5th, ... read
				color = (color & 0x0f);
			}
			else
			{
				// 2nd, 4th, 6th, ... read
				color = (color & 0xf0) >> 4;
				gfxaddr++;
			}

			readflag ^= 1;

			tflag = 1;

			if (pastelgl_paltbl[color] & 0xf0)
			{
				if (!color) tflag = 0;
				drawcolor = ((pastelgl_palbank * 0x10) + color);
			}
			else
			{
				drawcolor = ((pastelgl_palbank * 0x10) + pastelgl_paltbl[color]);
			}

			if (tflag)
			{
				pastelgl_videoram[(dy * Machine->drv->screen_width) + dx] = drawcolor;
				plot_pixel(pastelgl_tmpbitmap, dx, dy, Machine->pens[drawcolor]);
			}

			nb1413m3_busyctr++;
		}
	}

	nb1413m3_busyflag = (nb1413m3_busyctr > 7000) ? 0 : 1;
}

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


******************************************************************************/
VIDEO_START( pastelgl )
{
	if ((pastelgl_tmpbitmap = auto_bitmap_alloc(Machine->drv->screen_width, Machine->drv->screen_height)) == 0) return 1;
	if ((pastelgl_videoram = auto_malloc(Machine->drv->screen_width * Machine->drv->screen_height * sizeof(char))) == 0) return 1;
	if ((pastelgl_paltbl = auto_malloc(0x10 * sizeof(char))) == 0) return 1;
	memset(pastelgl_videoram, 0x00, (Machine->drv->screen_width * Machine->drv->screen_height * sizeof(char)));
	return 0;
}

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


******************************************************************************/
VIDEO_UPDATE( pastelgl )
{
	int x, y;
	unsigned char color;

	if (get_vh_global_attribute_changed() || pastelgl_screen_refresh)
	{
		pastelgl_screen_refresh = 0;

		for (y = 0; y < Machine->drv->screen_height; y++)
		{
			for (x = 0; x < Machine->drv->screen_width; x++)
			{
				color = pastelgl_videoram[(y * Machine->drv->screen_width) + x];
				plot_pixel(pastelgl_tmpbitmap, x, y, Machine->pens[color]);
			}
		}
	}

	if (pastelgl_dispflag)
	{
		copybitmap(bitmap, pastelgl_tmpbitmap, 0, 0, 0, 0, &Machine->visible_area, TRANSPARENCY_NONE, 0);
	}
	else
	{
		fillbitmap(bitmap, Machine->pens[0x00], 0);
	}
}
