/***************************************************************************
						WEC Le Mans 24  &   Hot Chase

					      (C)   1986 & 1988 Konami

					driver by	Luca Elia (eliavit@unina.it)


Note:	if MAME_DEBUG is defined, pressing Z with:

		Q		shows background layer
		W		shows foreground layer
		E		shows text layer
		R		shows road layer
		A		shows sprites
		B		toggles the custom gfx browser on/off

		Keys can be used togheter!

							[WEC Le Mans 24]

[ 2 Scrolling Layers ]
	[Background]
	[Foreground]
		Tile Size:				8x8

		Tile Format:
										Colour?
				---- ba98 7654 3210		Code

		Layer Size:				4 Pages -	Page0 Page1
											Page2 Page3
								each page is 512 x 256 (64 x 32 tiles)

		Page Selection Reg.:	108efe	[Bg]
								108efc	[Fg]
								4 pages to choose from

		Scrolling Columns:		1
		Scrolling Columns Reg.:	108f26	[Bg]
								108f24	[Fg]

		Scrolling Rows:			224 / 8 (Screen-wise scrolling)
		Scrolling Rows Reg.:	108f82/4/6..	[Bg]
								108f80/2/4..	[Fg]

[ 1 Text Layer ]
		Tile Size:				8x8

		Tile Format:
				fedc ba9- ---- ----		Colour: ba9 fedc
				---- ba98 7654 3210		Code

		Layer Size:				1 Page: 512 x 256 (64 x 32 tiles)

		Scrolling:				-

[ 1 Road Layer ]

[ 256 Sprites ]
	Zooming Sprites, see below



								[Hot Chase]

[ 3 Zooming Layers ]
	[Background]
	[Foreground (text)]
	[Road]

[ 256 Sprites ]
	Zooming Sprites, see below


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

/* Variables only used here: */

static struct tilemap *bg_tilemap, *fg_tilemap, *txt_tilemap;
static struct sprite_list *sprite_list;


/* Variables that driver has acces to: */

unsigned char *wecleman_pageram, *wecleman_txtram, *wecleman_roadram, *wecleman_unknown;
int wecleman_roadram_size, wecleman_bgpage[4], wecleman_fgpage[4], *wecleman_gfx_bank;

unsigned char *hotchase_bgram, *hotchase_fgram, *hotchase_bgreg, *hotchase_fgreg;



/* Variables defined in driver: */

extern int wecleman_selected_ip, wecleman_irqctrl;



/***************************************************************************
							Common routines
***************************************************************************/

/* Useful defines - for debug */
#define KEY(_k_,_action_) \
	if (keyboard_pressed(KEYCODE_##_k_))	{ while (keyboard_pressed(KEYCODE_##_k_)); _action_ }
#define KEY_SHIFT(_k_,_action_) \
	if ( (keyboard_pressed(KEYCODE_LSHIFT)||keyboard_pressed(KEYCODE_RSHIFT)) && \
	      keyboard_pressed(KEYCODE_##_k_) )	{ while (keyboard_pressed(KEYCODE_##_k_)); _action_ }
#define KEY_FAST(_k_,_action_) \
	if (keyboard_pressed(KEYCODE_##_k_))	{ _action_ }


/* WEC Le Mans 24 and Hot Chase share the same sprite hardware */
#define NUM_SPRITES 256


void paletteram_SBGRBBBBGGGGRRRR_word_w(int offset, int data)
{
	/*	byte 0    	byte 1		*/
	/*	SBGR BBBB 	GGGG RRRR	*/
	/*	S000 4321 	4321 4321	*/
	/*  S = Shade				*/

	int oldword = READ_WORD (&paletteram[offset]);
	int newword = COMBINE_WORD (oldword, data);

	int r = ((newword << 1) & 0x1E ) | ((newword >> 12) & 0x01);
	int g = ((newword >> 3) & 0x1E ) | ((newword >> 13) & 0x01);
	int b = ((newword >> 7) & 0x1E ) | ((newword >> 14) & 0x01);

	/* This effect can be turned on/off actually ... */
	if (newword & 0x8000)	{ r /= 2;	 g /= 2;	 b /= 2; }

	palette_change_color( offset/2,	 (r * 0xFF) / 0x1F,
									 (g * 0xFF) / 0x1F,
									 (b * 0xFF) / 0x1F	 );

	WRITE_WORD (&paletteram[offset], newword);
}




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

					  Callbacks for the TileMap code

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



/***************************************************************************
								WEC Le Mans 24
***************************************************************************/

#define PAGE_NX  		(0x40)
#define PAGE_NY  		(0x20)
#define PAGE_GFX		(0)
#define TILEMAP_DIMY	(PAGE_NY * 2 * 8)

/*------------------------------------------------------------------------
				[ Frontmost (text) layer + video registers ]
------------------------------------------------------------------------*/



void wecleman_get_txt_tile_info( int col, int row )
{
	int tile_index	=	col + row * PAGE_NX;
	int code 		=	READ_WORD(&wecleman_txtram[tile_index*2]);
	SET_TILE_INFO(PAGE_GFX, code & 0xfff, (code >> 12) + ((code >> 5) & 0x70) );
}




int wecleman_txtram_r(int offset)
{
	return READ_WORD(&wecleman_txtram[offset]);
}




void wecleman_txtram_w(int offset, int data)
{
	int old_data = READ_WORD(&wecleman_txtram[offset]);
	int new_data = COMBINE_WORD(old_data,data);

	if ( old_data != new_data )
	{
		WRITE_WORD(&wecleman_txtram[offset], new_data);

		if (offset >= 0xE00 )	/* Video registers */
		{
			/* pages selector for the background */
			if (offset == 0xEFE)
			{
				wecleman_bgpage[0] = (new_data >> 0x4) & 3;
				wecleman_bgpage[1] = (new_data >> 0x0) & 3;
				wecleman_bgpage[2] = (new_data >> 0xc) & 3;
				wecleman_bgpage[3] = (new_data >> 0x8) & 3;
				tilemap_mark_all_tiles_dirty(bg_tilemap);
			}

			/* pages selector for the foreground */
			if (offset == 0xEFC)
			{
				wecleman_fgpage[0] = (new_data >> 0x4) & 3;
				wecleman_fgpage[1] = (new_data >> 0x0) & 3;
				wecleman_fgpage[2] = (new_data >> 0xc) & 3;
				wecleman_fgpage[3] = (new_data >> 0x8) & 3;
				tilemap_mark_all_tiles_dirty(fg_tilemap);
			}

			/* Parallactic horizontal scroll registers follow */

		}
		else
			tilemap_mark_tile_dirty(txt_tilemap,(offset/2) % PAGE_NX,(offset/2) / PAGE_NX);
	}
}




/*------------------------------------------------------------------------
							[ Background ]
------------------------------------------------------------------------*/



void wecleman_get_bg_tile_info( int col, int row )
{
	int tile_index	=	(col % PAGE_NX) + (row % PAGE_NY) * PAGE_NX;
	int page		=	wecleman_bgpage[(col / PAGE_NX) + (row / PAGE_NY) * 2];
	int code 		=	READ_WORD(&wecleman_pageram[tile_index*2 + page*(PAGE_NX*PAGE_NY*2)]);
	SET_TILE_INFO(PAGE_GFX, code & 0xfff, (code >> 12) + ((code >> 5) & 0x70) );
}




/*------------------------------------------------------------------------
							[ Foreground ]
------------------------------------------------------------------------*/



void wecleman_get_fg_tile_info( int col, int row )
{
	int tile_index	=	(col % PAGE_NX) + (row % PAGE_NY) * PAGE_NX;
	int page		=	wecleman_fgpage[(col / PAGE_NX) + (row / PAGE_NY) * 2];
	int code 		=	READ_WORD(&wecleman_pageram[tile_index*2 + page*(PAGE_NX*PAGE_NY*2)]);
	SET_TILE_INFO(PAGE_GFX, code & 0xfff, (code >> 12) + ((code >> 5) & 0x70) );
}






/*------------------------------------------------------------------------
					[ Pages (Background & Foreground) ]
------------------------------------------------------------------------*/



/* Pages that compose both the background and the foreground */
int wecleman_pageram_r(int offset)
{
	return READ_WORD(&wecleman_pageram[offset]);
}


void wecleman_pageram_w(int offset, int data)
{
	int old_data = READ_WORD(&wecleman_pageram[offset]);
	int new_data = COMBINE_WORD(old_data,data);

	if ( old_data != new_data )
	{
		int page,row,col;

		WRITE_WORD(&wecleman_pageram[offset], new_data);

		page	=	( offset / 2			) / (PAGE_NX * PAGE_NY);
		col		=	( offset / 2			) % PAGE_NX;
		row		=	( offset / 2 / PAGE_NX	) % PAGE_NY;

		/* background */
		if (wecleman_bgpage[0] == page)	tilemap_mark_tile_dirty(bg_tilemap, col,			row				);
		if (wecleman_bgpage[1] == page)	tilemap_mark_tile_dirty(bg_tilemap, col + PAGE_NX,	row				);
		if (wecleman_bgpage[2] == page)	tilemap_mark_tile_dirty(bg_tilemap, col, 			row + PAGE_NY	);
		if (wecleman_bgpage[3] == page)	tilemap_mark_tile_dirty(bg_tilemap, col + PAGE_NX,	row + PAGE_NY	);

		/* foreground */
		if (wecleman_fgpage[0] == page)	tilemap_mark_tile_dirty(fg_tilemap, col,			row				);
		if (wecleman_fgpage[1] == page)	tilemap_mark_tile_dirty(fg_tilemap, col + PAGE_NX,	row				);
		if (wecleman_fgpage[2] == page)	tilemap_mark_tile_dirty(fg_tilemap, col, 			row + PAGE_NY	);
		if (wecleman_fgpage[3] == page)	tilemap_mark_tile_dirty(fg_tilemap, col + PAGE_NX,	row + PAGE_NY	);
	}
}



/*------------------------------------------------------------------------
						[ Video Hardware Start ]
------------------------------------------------------------------------*/

int wecleman_vh_start(void)
{

/*
 Sprite banking - each bank is 0x20000 bytes (we support 0x40 bank codes)
 This games has ROMs for 16 banks
*/

	static int bank[0x40] = {	0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,
								8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,
								0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,
								8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15	};

	wecleman_gfx_bank = bank;


	bg_tilemap = tilemap_create(wecleman_get_bg_tile_info,
								TILEMAP_TRANSPARENT,	/* We draw part of the road below */
								8,8,
								PAGE_NX * 2, PAGE_NY * 2 );

	fg_tilemap = tilemap_create(wecleman_get_fg_tile_info,
								TILEMAP_TRANSPARENT,
								8,8,
								PAGE_NX * 2, PAGE_NY * 2);

	txt_tilemap = tilemap_create(wecleman_get_txt_tile_info,
								TILEMAP_TRANSPARENT,
								8,8,
								PAGE_NX * 1, PAGE_NY * 1);


	sprite_list = sprite_list_create( NUM_SPRITES, SPRITE_LIST_BACK_TO_FRONT | SPRITE_LIST_RAW_DATA );


	if (bg_tilemap && fg_tilemap && txt_tilemap && sprite_list)
	{
		tilemap_set_scroll_rows(bg_tilemap, TILEMAP_DIMY);	/* Screen-wise scrolling */
		tilemap_set_scroll_cols(bg_tilemap, 1);
		bg_tilemap->transparent_pen = 0;

		tilemap_set_scroll_rows(fg_tilemap, TILEMAP_DIMY);	/* Screen-wise scrolling */
		tilemap_set_scroll_cols(fg_tilemap, 1);
		fg_tilemap->transparent_pen = 0;

		tilemap_set_scroll_rows(txt_tilemap, 1);
		tilemap_set_scroll_cols(txt_tilemap, 1);
		txt_tilemap->transparent_pen = 0;
		tilemap_set_scrollx(txt_tilemap,0, 512-320-16 );	/* fixed scrolling? */
		tilemap_set_scrolly(txt_tilemap,0, 0 );

		sprite_list->max_priority = 0;
		sprite_list->sprite_type = SPRITE_TYPE_ZOOM;

		return 0;
	}
	else return 1;
}













/***************************************************************************
								Hot Chase
***************************************************************************/

/*
Hot Chase Logo:
00F9 0000 000F 00F8-0000 0000 0010 00B0
0000 0000 000F 00F8-0000 0000 0001 0000
*/
void hotchase_bgreg_w(int offset,int data)
{
int regs[0x20/4];
int i;

	COMBINE_WORD_MEM(&hotchase_bgreg[offset],data);

	for (i = 0; i < 0x20; i+=4)
	{
		regs[i/4] = ( READ_WORD(&hotchase_bgreg[i+0]) & 0xff ) * 256 +
					( READ_WORD(&hotchase_bgreg[i+2]) & 0xff );
	}

	tilemap_set_scrollx(bg_tilemap,0,regs[0]>>3);
	tilemap_set_scrolly(bg_tilemap,0,regs[3]>>3);

#if 0
{
	char buf[80];
	sprintf(buf,"%04X %04X %04X %04X - %04X %04X %04X %04X",
				regs[0],regs[1],regs[2],regs[3],
				regs[4],regs[5],regs[6],regs[7]);

	usrintf_showmessage(buf);
}
#endif
}

void hotchase_fgreg_w(int offset,int data)
{
int regs[0x20/4];
int i;

	COMBINE_WORD_MEM(&hotchase_fgreg[offset],data);

	for (i = 0; i < 0x20; i+=4)
	{
		regs[i/4] = ( READ_WORD(&hotchase_fgreg[i+0]) & 0xff ) * 256 +
					( READ_WORD(&hotchase_fgreg[i+2]) & 0xff );
	}

#if 0
{
	char buf[80];
	tilemap_set_scrollx(fg_tilemap,0,regs[0]>>3);
	tilemap_set_scrolly(fg_tilemap,0,regs[3]>>3);

	sprintf(buf,"%04X %04X %04X %04X - %04X %04X %04X %04X",
				regs[0],regs[1],regs[2],regs[3],
				regs[4],regs[5],regs[6],regs[7]);

	usrintf_showmessage(buf);
}
#endif
}



/*------------------------------------------------------------------------
							[ Background ]
------------------------------------------------------------------------*/



#define BG_NX  (0x20)
#define BG_NY  (0x20)
#define BG_GFX (0)


static void hotchase_get_bg_tile_info( int col, int row )
{
	int tile_index	=	col + row * BG_NX;
	int code 		=	(READ_WORD(&hotchase_bgram[tile_index*2 + 0x000]) & 0xFF ) +
						(READ_WORD(&hotchase_bgram[tile_index*2 + 0x800]) & 0xFF ) * 256;
	SET_TILE_INFO(BG_GFX, code & 0x03ff, (code >> 10));
}



void hotchase_bgram_w(int offset,int data)
{
int old_data, new_data;

	old_data  = READ_WORD(&hotchase_bgram[offset]);
	COMBINE_WORD_MEM(&hotchase_bgram[offset],data);
	new_data  = READ_WORD(&hotchase_bgram[offset]);

	if (old_data != new_data)
		tilemap_mark_tile_dirty(bg_tilemap,((offset % 0x800)/2) % BG_NX,((offset % 0x800)/2) / BG_NX);
}







/*------------------------------------------------------------------------
							[ Foreground ]
------------------------------------------------------------------------*/



#define FG_NX  (0x20)
#define FG_NY  (0x20)
#define FG_GFX (1)


static void hotchase_get_fg_tile_info( int col, int row )
{
	int tile_index	=	col + row * FG_NX;
	int code 		=	(READ_WORD(&hotchase_fgram[tile_index*2 + 0x000]) & 0xFF ) +
						(READ_WORD(&hotchase_fgram[tile_index*2 + 0x800]) & 0xFF ) * 256;
	SET_TILE_INFO(FG_GFX, code & 0x03ff, code >> 7 );
}



void hotchase_fgram_w(int offset,int data)
{
int old_data, new_data;

	old_data  = READ_WORD(&hotchase_fgram[offset]);
	COMBINE_WORD_MEM(&hotchase_fgram[offset],data);
	new_data  = READ_WORD(&hotchase_fgram[offset]);

	if (old_data != new_data)
		tilemap_mark_tile_dirty(fg_tilemap,((offset % 0x800)/2) % FG_NX,((offset % 0x800)/2) / FG_NX);
}





/*------------------------------------------------------------------------
						[ Video Hardware Start ]
------------------------------------------------------------------------*/

/* for the zoomed layers we support: road and fg */
static struct osd_bitmap *temp_bitmap, *temp_bitmap2;

int hotchase_vh_start(void)
{
/*
 Sprite banking - each bank is 0x20000 bytes (we support 0x40 bank codes)
 This games has ROMs for 0x30 banks
*/
	static int bank[0x40] = {	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
								16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
								32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
								0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15	};
	wecleman_gfx_bank = bank;


	temp_bitmap  = osd_create_bitmap(512,512);
	temp_bitmap2 = osd_create_bitmap(512,256);

	bg_tilemap = tilemap_create(hotchase_get_bg_tile_info,
								TILEMAP_OPAQUE,
								16,16,
								BG_NX,BG_NY );

	fg_tilemap = tilemap_create(hotchase_get_fg_tile_info,
								TILEMAP_TRANSPARENT,
								16,16,
								FG_NX,FG_NY );

	sprite_list = sprite_list_create( NUM_SPRITES, SPRITE_LIST_BACK_TO_FRONT | SPRITE_LIST_RAW_DATA );

	if (bg_tilemap && fg_tilemap && temp_bitmap && temp_bitmap2 && sprite_list)
	{
	struct rectangle clip = {0,512-1, 0, 512-1};

		tilemap_set_scroll_rows(bg_tilemap,1);
		tilemap_set_scroll_cols(bg_tilemap,1);

		tilemap_set_scroll_rows(fg_tilemap,1);
		tilemap_set_scroll_cols(fg_tilemap,1);
		fg_tilemap->transparent_pen = 0;
		tilemap_set_clip( fg_tilemap, &clip );

		sprite_list->max_priority = 0;
		sprite_list->sprite_type = SPRITE_TYPE_ZOOM;

		return 0;
	}
	else return 1;
}

void hotchase_vh_stop(void)
{
	if (temp_bitmap)	osd_free_bitmap(temp_bitmap);
	if (temp_bitmap2)	osd_free_bitmap(temp_bitmap2);
}







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

								Road Drawing

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


/***************************************************************************
								WEC Le Mans 24
***************************************************************************/

#define ROAD_COLOR(x)	(0x00 + ((x)&0xff))

void wecleman_mark_road_colors(void)
{
	int y					=	Machine->drv->visible_area.min_y;
	int ymax				=	Machine->drv->visible_area.max_y;
	int color_codes_start	=	Machine->drv->gfxdecodeinfo[1].color_codes_start;

	for (; y <= ymax; y++)
	{
		int color = ROAD_COLOR( READ_WORD(&wecleman_roadram[0x400 + y * 2]) );
		memset(&palette_used_colors[color_codes_start + color*8],PALETTE_COLOR_USED,8);	// no transparency
	}
}


/*

	This layer is composed of horizontal lines gfx elements
	There are 256 lines in ROM, each is 512 pixels wide

	Offset:		Elements:	Data:

	0000-01ff	100 Words	Code

		fedcba98--------	Priority?
		--------76543210	Line Number

	0200-03ff	100 Words	Horizontal Scroll
	0400-05ff	100 Words	Color
	0600-07ff	100 Words	??

	We draw each line using a bunch of 64x1 tiles

*/

void wecleman_draw_road(struct osd_bitmap *bitmap,int priority)
{
struct rectangle rect = Machine->drv->visible_area;
int curr_code, sx,sy;

/* Referred to what's in the ROMs */
#define XSIZE 512
#define YSIZE 256

	/* Let's draw from the top to the bottom of the visible screen */
	for (sy = rect.min_y ; sy <= rect.max_y ; sy ++)
	{
		int code		=	READ_WORD(&wecleman_roadram[(YSIZE*0+sy)*2]);
		int scrollx 	=	READ_WORD(&wecleman_roadram[(YSIZE*1+sy)*2]) + 24;	// fudge factor :)
		int attr		=	READ_WORD(&wecleman_roadram[(YSIZE*2+sy)*2]);

		/* high byte is a priority information? */
		if ((code>>8) != priority)	continue;

		/* line number converted to tile number (each tile is 64x1) */
		code		=	(code % YSIZE) * (XSIZE/64);

		/* Scroll value applies to a "picture" twice as wide as the gfx
		   in ROM: left half is color 15, right half is the gfx */
		scrollx %= XSIZE * 2;

		if (scrollx >= XSIZE)	{curr_code = code+(scrollx-XSIZE)/64;	code = 0;}
		else					{curr_code = 0   + scrollx/64;}

		for (sx = -(scrollx % 64) ; sx <= rect.max_x ; sx += 64)
		{
			drawgfx(bitmap,Machine->gfx[1],
				curr_code++,
				ROAD_COLOR(attr),
				0,0,
				sx,sy,
				&rect,
				TRANSPARENCY_NONE,0);

			if ( (curr_code % (XSIZE/64)) == 0)	curr_code = code;
		}
	}

#undef XSIZE
#undef YSIZE
}






/***************************************************************************
							Hot Chase
***************************************************************************/




void hotchase_mark_road_colors(void)
{
	int y					=	Machine->drv->visible_area.min_y;
	int ymax				=	Machine->drv->visible_area.max_y;
	int color_codes_start	=	Machine->drv->gfxdecodeinfo[2].color_codes_start;

	for (; y <= ymax; y++)
	{
		int color = (READ_WORD(&wecleman_roadram[y * 4]) >> 4 ) & 0xf;
		palette_used_colors[color_codes_start + color*16 + 0] = PALETTE_COLOR_TRANSPARENT;	// pen 0 transparent
		memset(&palette_used_colors[color_codes_start + color*16 + 1],PALETTE_COLOR_USED,16-1);
	}

}




/*
	This layer is composed of horizontal lines gfx elements
	There are 512 lines in ROM, each is 512 pixels wide

	Offset:		Elements:	Data:

	0000-03ff	00-FF		Code (4 bytes)

	Code:

		00.w
				fedc ba98 ---- ----		Unused?
				---- ---- 7654 ----		color
				---- ---- ---- 3210		scroll x

		02.w	fedc ba-- ---- ----		scroll x
				---- --9- ---- ----		?
				---- ---8 7654 3210		code

	We draw each line using a bunch of 64x1 tiles

*/

void hotchase_draw_road(struct osd_bitmap *bitmap,int priority, struct rectangle *clip)
{
struct rectangle rect = *clip;
int sy;


/* Referred to what's in the ROMs */
#define XSIZE 512
#define YSIZE 512


	/* Let's draw from the top to the bottom of the visible screen */
	for (sy = rect.min_y ; sy <= rect.max_y ; sy ++)
	{
		int curr_code,sx;
		int code	=	  READ_WORD(&wecleman_roadram[0x0000+sy*4+2]) +
						( READ_WORD(&wecleman_roadram[0x0000+sy*4+0]) << 16 );
		int color	=	(( code & 0x00f00000 ) >> 20 ) + 0x70;
		int scrollx =	 ( code & 0x000ffc00 ) >> 10;
		code		=	 ( code & 0x000003ff ) >>  0;

		/* convert line number in gfx element number: */
		/* code is the tile code of the start of this line */
		code	= ( code % YSIZE ) * ( XSIZE / 64 );

//		if (scrollx < 0) scrollx += XSIZE * 2 ;
		scrollx %= XSIZE * 2;

		if (scrollx < XSIZE)	{curr_code = code + scrollx/64;	code = 0;}
		else					{curr_code = 0    + scrollx/64;}

		for (sx = -(scrollx % 64) ; sx <= rect.max_x ; sx += 64)
		{
			drawgfx(bitmap,Machine->gfx[2],
				curr_code++,
				color,
				0,0,
				sx,sy,
				&rect,
				TRANSPARENCY_PEN,0);

			/* Maybe after the end of a line of gfx we shouldn't
			   wrap around, but pad with a value */
			if ((curr_code % (XSIZE/64)) == 0)	curr_code = code;
		}
	}

#undef XSIZE
#undef YSIZE
}




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

							Sprites Drawing

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

/* Hot Chase: shadow of trees is pen 0x0a - Should it be black like it is now */

static void mark_sprites_colors(void)
{
	int offs;

	for (offs = 0; offs < (NUM_SPRITES * 0x10); offs += 0x10)
	{
		int dest_y, dest_h, color;

		dest_y = READ_WORD(&spriteram[offs + 0x00]);
		if (dest_y == 0xFFFF)	break;

		dest_h = (dest_y >> 8) - (dest_y & 0x00FF);
		if (dest_h < 1) continue;

		color = (READ_WORD(&spriteram[offs + 0x04]) >> 8) & 0x7f;
		memset(&palette_used_colors[color*16 + 1], PALETTE_COLOR_USED, 16 - 2 );

		// pens 0 & 15 are transparent
		palette_used_colors[color*16 + 0] = palette_used_colors[color*16 + 15] = PALETTE_COLOR_TRANSPARENT;
	}
}




/*

	Sprites: 256 entries, 16 bytes each, first ten bytes used (and tested)

	Offset	Bits					Meaning

	00.w	fedc ba98 ---- ----		Screen Y start
			---- ---- 7654 3210		Screen Y stop

	02.w	fedc ba-- ---- ----		High bits of sprite "address"
			---- --9- ---- ----		Flip Y ?
			---- ---8 7654 3210		Screen X start

	04.w	fedc ba98 ---- ----		Color
			---- ---- 7654 3210		Source Width / 8

	06.w	f--- ---- ---- ----		Flip X
			-edc ba98 7654 3210		Low bits of sprite "address"

	08.w	--dc ba98 ---- ----		Y? Shrink Factor
			---- ---- --54 3210		X? Shrink Factor

Sprite "address" is the index of the pixel the hardware has to start
fetching data from, divided by 8. Only on screen height and source data
width are provided, along with two shrinking factors. So on screen width
and source height are calculated by the hardware using the shrink factors.
The factors are in the range 0 (no shrinking) - 3F (half size).

*/

static void get_sprite_info(void)
{
const unsigned short *base_pal	= Machine->gfx[0]->colortable + 0;
const unsigned char  *base_gfx	= Machine->memory_region[2];

const int gfx_max = Machine->memory_region_length[2];

unsigned char *source		=	spriteram;
struct sprite *sprite		=	sprite_list->sprite;
const struct sprite *finish	=	sprite + NUM_SPRITES;

int visibility = SPRITE_VISIBLE;


#define SHRINK_FACTOR(x) \
	(1.0 - ( ( (x) & 0x3F ) / 63.0) * 0.5)

	for (; sprite < finish; sprite++,source+=0x10)
	{
		int code, gfx, zoom;

		sprite->priority = 0;

		sprite->y	= READ_WORD(&source[0x00]);
		if (sprite->y == 0xFFFF)	{ visibility = 0; }

		sprite->flags = visibility;
		if (visibility==0) continue;

		sprite->total_height = (sprite->y >> 8) - (sprite->y & 0xFF);
		if (sprite->total_height < 1) {sprite->flags = 0;	continue;}

		sprite->x	 		=	READ_WORD(&source[0x02]);
		sprite->tile_width	=	READ_WORD(&source[0x04]);
		code				=	READ_WORD(&source[0x06]);
		zoom				=	READ_WORD(&source[0x08]);

		gfx	= (wecleman_gfx_bank[(sprite->x >> 10) & 0x3f] << 15) +  (code & 0x7fff);
		sprite->pal_data = base_pal + ( (sprite->tile_width >> 4) & 0x7f0 );	// 16 colors = 16 shorts

		if (code & 0x8000)
		{	sprite->flags |= SPRITE_FLIPX;	gfx += 1 - (sprite->tile_width & 0xFF);	};

		if (sprite->x & 0x0200)		/* ?flip y? */
		{	sprite->flags |= SPRITE_FLIPY; }

		gfx *= 8;

		sprite->pen_data = base_gfx + gfx;

		sprite->tile_width	= (sprite->tile_width & 0xFF) * 8;
		if (sprite->tile_width < 1) {sprite->flags = 0;	continue;}

		sprite->tile_height = sprite->total_height * ( 1.0 / SHRINK_FACTOR(zoom>>8) );
		sprite->x   = (sprite->x & 0x1ff) - 0xc0;
		sprite->y   = (sprite->y & 0xff);
		sprite->total_width = sprite->tile_width * SHRINK_FACTOR(zoom & 0xFF);

		sprite->line_offset = sprite->tile_width;

		/* Bound checking */
		if ((gfx + sprite->tile_width * sprite->tile_height - 1) >= gfx_max )
			{sprite->flags = 0;	continue;}
	}
}



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

							Browse the graphics

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

/*
	Use:
	* LEFT, RIGHT, UP, DOWN and PGUP/PGDN to move around
	* SHIFT + PGUP/PGDN to move around faster
	* SHIFT + LEFT/RIGHT to change the width of the graphics
	* SHIFT + RCTRL to go back to the start of the gfx

*/
void browser(struct osd_bitmap *bitmap)
{
const unsigned short *base_pal	= Machine->gfx[0]->colortable + 0;
const unsigned char  *base_gfx	= Machine->memory_region[2];

const int gfx_max				= Machine->memory_region_length[2];

struct sprite *sprite		=	sprite_list->sprite;
const struct sprite *finish	=	sprite + NUM_SPRITES;

static int w = 32, gfx;
char buf[80];

	for ( ; sprite < finish ; sprite++)	sprite->flags = 0;

	sprite = sprite_list->sprite;

	sprite->flags = SPRITE_VISIBLE;
	sprite->x = 0;
	sprite->y = 0;
	sprite->tile_height = sprite->total_height = 224;
	sprite->pal_data = base_pal;

	KEY_FAST(LEFT,	gfx-=8;)
	KEY_FAST(RIGHT,	gfx+=8;)
	KEY_FAST(UP,	gfx-=w;)
	KEY_FAST(DOWN,	gfx+=w;)

	KEY_SHIFT(PGDN,	gfx -= 0x100000;)
	KEY_SHIFT(PGUP,	gfx += 0x100000;)

	KEY(PGDN,gfx+=w*sprite->tile_height;)
	KEY(PGUP,gfx-=w*sprite->tile_height;)

	KEY_SHIFT(RCONTROL,	gfx = 0;)

	gfx %= gfx_max;
	if (gfx < 0)	gfx += gfx_max;

	KEY_SHIFT(LEFT,		w-=8;)
	KEY_SHIFT(RIGHT,	w+=8;)
	w &= 0x1ff;

	sprite->pen_data = base_gfx + gfx;
	sprite->tile_width = sprite->total_width = sprite->line_offset = w;

	/* Bound checking */
	if ((gfx + sprite->tile_width * sprite->tile_height - 1) >= gfx_max )
		sprite->flags = 0;

	sprite_draw( sprite_list, 0 );

	sprintf(buf,"W:%02X GFX/8: %X",w,gfx / 8);
	usrintf_showmessage(buf);
}












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

							Screen Drawing

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

#define WECLEMAN_TVKILL \
	if ((wecleman_irqctrl & 0x40)==0) layers_ctrl = 0;	// TV-KILL

#define WECLEMAN_LAMPS \
	osd_led_w(0,(wecleman_selected_ip >> 2)& 1); 		// Start lamp



/* You can activate each single layer of gfx */
#define WECLEMAN_LAYERSCTRL \
{ \
	static int browse = 0; \
	KEY(B, browse ^= 1;) \
	if (browse) \
	{ \
		osd_clearbitmap(Machine->scrbitmap); \
		browser(bitmap); \
		return; \
	} \
	if (keyboard_pressed(KEYCODE_Z)) \
	{ \
	int msk = 0; \
	 \
		if (keyboard_pressed(KEYCODE_Q))	{ msk |= 0xffe1;} \
		if (keyboard_pressed(KEYCODE_W))	{ msk |= 0xffe2;} \
		if (keyboard_pressed(KEYCODE_E))	{ msk |= 0xffe4;} \
		if (keyboard_pressed(KEYCODE_A))	{ msk |= 0xffe8;} \
		if (keyboard_pressed(KEYCODE_R))	{ msk |= 0xfff0;} \
		if (msk != 0) layers_ctrl &= msk; \
	} \
}


/***************************************************************************
							WEC Le Mans 24
***************************************************************************/

void wecleman_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
{
	int i, layers_ctrl = 0xFFFF;


	WECLEMAN_LAMPS

	WECLEMAN_TVKILL

#ifdef MAME_DEBUG
	WECLEMAN_LAYERSCTRL
#endif

{
/* Set the scroll values for the scrolling layers */

	/* y values */
	int bg_y = READ_WORD(&wecleman_txtram[0x0F24+2]) & (TILEMAP_DIMY - 1);
	int fg_y = READ_WORD(&wecleman_txtram[0x0F24+0]) & (TILEMAP_DIMY - 1);

	tilemap_set_scrolly(bg_tilemap, 0, bg_y );
	tilemap_set_scrolly(fg_tilemap, 0, fg_y );

	/* x values */
	for ( i = 0 ; i < 28; i++ )
	{
		int j;
		int bg_x = 0xB0 + READ_WORD(&wecleman_txtram[0xF80+i*4+2]);
		int fg_x = 0xB0 + READ_WORD(&wecleman_txtram[0xF80+i*4+0]);

		for ( j = 0 ; j < 8; j++ )
		{
			tilemap_set_scrollx(bg_tilemap, (bg_y + i*8 + j) & (TILEMAP_DIMY - 1), bg_x );
			tilemap_set_scrollx(fg_tilemap, (fg_y + i*8 + j) & (TILEMAP_DIMY - 1), fg_x );
		}
	}
}


	tilemap_update(ALL_TILEMAPS);
	get_sprite_info();

	palette_init_used_colors();

	wecleman_mark_road_colors();
	mark_sprites_colors();

	sprite_update();

	if (palette_recalc())	tilemap_mark_all_pixels_dirty(ALL_TILEMAPS);


	osd_clearbitmap(Machine->scrbitmap);

	/* Draw the road (lines which have "priority" 0x02) */
	if (layers_ctrl & 16)	wecleman_draw_road(bitmap,0x02);

	/* Draw the background */
	if (layers_ctrl & 1)
	{
		tilemap_render(bg_tilemap);
		tilemap_draw(bitmap, bg_tilemap,  0);
	}

	/* Draw the foreground */
	if (layers_ctrl & 2)
	{
		tilemap_render(fg_tilemap);
		tilemap_draw(bitmap, fg_tilemap,  0);
	}

	/* Draw the road (lines which have "priority" 0x04) */
	if (layers_ctrl & 16)	wecleman_draw_road(bitmap,0x04);

	/* Draw the sprites */
	if (layers_ctrl & 8)	sprite_draw(sprite_list,0);

	/* Draw the text layer */
	if (layers_ctrl & 4)
	{
		tilemap_render(txt_tilemap);
		tilemap_draw(bitmap, txt_tilemap,  0);
	}

}








/***************************************************************************
								Hot Chase
***************************************************************************/

void hotchase_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
{
	int layers_ctrl = 0xFFFF;

	WECLEMAN_LAMPS

	WECLEMAN_TVKILL

#ifdef MAME_DEBUG
	WECLEMAN_LAYERSCTRL
#endif

	tilemap_update(ALL_TILEMAPS);
	get_sprite_info();

	palette_init_used_colors();

	hotchase_mark_road_colors();
	mark_sprites_colors();
	sprite_update();

	if (palette_recalc())	tilemap_mark_all_pixels_dirty(ALL_TILEMAPS);

	/* Draw the background */
	if (layers_ctrl & 1)
	{
		tilemap_render(bg_tilemap);
		tilemap_draw(bitmap, bg_tilemap,  0);
	}
	else	osd_clearbitmap(Machine->scrbitmap);

	/* Draw the road */
	if (layers_ctrl & 16)
	{
	struct rectangle clip = {0, 512-1, 0, 256-1};

		fillbitmap(temp_bitmap2,0,0);

		hotchase_draw_road(temp_bitmap2,0,&clip);

		copybitmapzoom(	bitmap, temp_bitmap2,
						0, 0,							// flip
						-(64+32)*4+32, 0,				// pos
						&Machine->drv->visible_area,	// clip
						TRANSPARENCY_PEN,0,				// transparency
						(2<<16),(1<<16)					// scale: 16.16 fixed
						);
	}

	/* Draw the sprites */
	if (layers_ctrl & 8)	sprite_draw(sprite_list,0);

	/* Draw the foreground (text) */
	if (layers_ctrl & 4)
	{
		tilemap_render(fg_tilemap);
		fillbitmap(temp_bitmap,fg_tilemap->transparent_pen,0);
		tilemap_draw(temp_bitmap, fg_tilemap,  0);

		copybitmapzoom(	bitmap, temp_bitmap,
						0, 0,							// flip
						0, 0,							// pos
						&Machine->drv->visible_area,	// clip
						TRANSPARENCY_PEN,fg_tilemap->transparent_pen,
						(320<<16)/512,(256<<16)/480		// scale: 16.16 fixed
						);
	}

}
