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

    Atari Toobin' hardware

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

#include "driver.h"
#include "machine/atarigen.h"
#include "toobin.h"



/*************************************
 *
 *  Globals we own
 *
 *************************************/

static double brightness;



/*************************************
 *
 *  Tilemap callbacks
 *
 *************************************/

static TILE_GET_INFO( get_alpha_tile_info )
{
	UINT16 data = atarigen_alpha[tile_index];
	int code = data & 0x3ff;
	int color = (data >> 12) & 0x0f;
	SET_TILE_INFO(2, code, color, (data >> 10) & 1);
}


static TILE_GET_INFO( get_playfield_tile_info )
{
	UINT16 data1 = atarigen_playfield[tile_index * 2];
	UINT16 data2 = atarigen_playfield[tile_index * 2 + 1];
	int code = data2 & 0x3fff;
	int color = data1 & 0x0f;
	SET_TILE_INFO(0, code, color, TILE_FLIPYX(data2 >> 14));
	tileinfo->priority = (data1 >> 4) & 3;
}



/*************************************
 *
 *  Video system start
 *
 *************************************/

VIDEO_START( toobin )
{
	static const struct atarimo_desc modesc =
	{
		1,					/* index to which gfx system */
		1,					/* number of motion object banks */
		1,					/* are the entries linked? */
		0,					/* are the entries split? */
		0,					/* render in reverse order? */
		1,					/* render in swapped X/Y order? */
		0,					/* does the neighbor bit affect the next object? */
		1024,				/* pixels per SLIP entry (0 for no-slip) */
		0,					/* pixel offset for SLIPs */
		0,					/* maximum number of links to visit/scanline (0=all) */

		0x100,				/* base palette entry */
		0x100,				/* maximum number of colors */
		0,					/* transparent pen index */

		{{ 0,0,0x00ff,0 }},	/* mask for the link */
		{{ 0 }},			/* mask for the graphics bank */
		{{ 0,0x3fff,0,0 }},	/* mask for the code index */
		{{ 0 }},			/* mask for the upper code index */
		{{ 0,0,0,0x000f }},	/* mask for the color */
		{{ 0,0,0,0xffc0 }},	/* mask for the X position */
		{{ 0x7fc0,0,0,0 }},	/* mask for the Y position */
		{{ 0x0007,0,0,0 }},	/* mask for the width, in tiles*/
		{{ 0x0038,0,0,0 }},	/* mask for the height, in tiles */
		{{ 0,0x4000,0,0 }},	/* mask for the horizontal flip */
		{{ 0,0x8000,0,0 }},	/* mask for the vertical flip */
		{{ 0 }},			/* mask for the priority */
		{{ 0 }},			/* mask for the neighbor */
		{{ 0x8000,0,0,0 }},	/* mask for absolute coordinates */

		{{ 0 }},			/* mask for the special value */
		0,					/* resulting value to indicate "special" */
		0					/* callback routine for special entries */
	};

	/* initialize the playfield */
	atarigen_playfield_tilemap = tilemap_create(get_playfield_tile_info, tilemap_scan_rows, TILEMAP_OPAQUE, 8,8, 128,64);

	/* initialize the motion objects */
	atarimo_init(machine, 0, &modesc);

	/* initialize the alphanumerics */
	atarigen_alpha_tilemap = tilemap_create(get_alpha_tile_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 8,8, 64,48);
	tilemap_set_transparent_pen(atarigen_alpha_tilemap, 0);
}



/*************************************
 *
 *  Palette RAM write handler
 *
 *************************************/

WRITE16_HANDLER( toobin_paletteram_w )
{
	int newword;

	COMBINE_DATA(&paletteram16[offset]);
	newword = paletteram16[offset];

	{
		int red =   (((newword >> 10) & 31) * 224) >> 5;
		int green = (((newword >>  5) & 31) * 224) >> 5;
		int blue =  (((newword      ) & 31) * 224) >> 5;

		if (red) red += 38;
		if (green) green += 38;
		if (blue) blue += 38;

		palette_set_color(Machine, offset & 0x3ff, MAKE_RGB(red, green, blue));
		if (!(newword & 0x8000))
			palette_set_brightness(Machine, offset & 0x3ff, brightness);
		else
			palette_set_brightness(Machine, offset & 0x3ff, 1.0);
	}
}


WRITE16_HANDLER( toobin_intensity_w )
{
	int i;

	if (ACCESSING_LSB)
	{
		brightness = (double)(~data & 0x1f) / 31.0;

		for (i = 0; i < 0x400; i++)
			if (!(paletteram16[i] & 0x8000))
				palette_set_brightness(Machine, i, brightness);
	}
}



/*************************************
 *
 *  X/Y scroll handlers
 *
 *************************************/

WRITE16_HANDLER( toobin_xscroll_w )
{
	UINT16 oldscroll = *atarigen_xscroll;
	UINT16 newscroll = oldscroll;
	COMBINE_DATA(&newscroll);

	/* if anything has changed, force a partial update */
	if (newscroll != oldscroll)
		video_screen_update_partial(0, video_screen_get_vpos(0));

	/* update the playfield scrolling - hscroll is clocked on the following scanline */
	tilemap_set_scrollx(atarigen_playfield_tilemap, 0, newscroll >> 6);
	atarimo_set_xscroll(0, newscroll >> 6);

	/* update the data */
	*atarigen_xscroll = newscroll;
}


WRITE16_HANDLER( toobin_yscroll_w )
{
	UINT16 oldscroll = *atarigen_yscroll;
	UINT16 newscroll = oldscroll;
	COMBINE_DATA(&newscroll);

	/* if anything has changed, force a partial update */
	if (newscroll != oldscroll)
		video_screen_update_partial(0, video_screen_get_vpos(0));

	/* if bit 4 is zero, the scroll value is clocked in right away */
	tilemap_set_scrolly(atarigen_playfield_tilemap, 0, newscroll >> 6);
	atarimo_set_yscroll(0, (newscroll >> 6) & 0x1ff);

	/* update the data */
	*atarigen_yscroll = newscroll;
}



/*************************************
 *
 *  X/Y scroll handlers
 *
 *************************************/

WRITE16_HANDLER( toobin_slip_w )
{
	int oldslip = atarimo_0_slipram[offset];
	int newslip = oldslip;
	COMBINE_DATA(&newslip);

	/* if the SLIP is changing, force a partial update first */
	if (oldslip != newslip)
		video_screen_update_partial(0, video_screen_get_vpos(0));

	/* update the data */
	atarimo_0_slipram_w(offset, data, mem_mask);
}



/*************************************
 *
 *  Main refresh
 *
 *************************************/

VIDEO_UPDATE( toobin )
{
	struct atarimo_rect_list rectlist;
	mame_bitmap *mobitmap;
	int x, y, r;

	/* draw the playfield */
	fillbitmap(priority_bitmap, 0, cliprect);
	tilemap_draw(bitmap, cliprect, atarigen_playfield_tilemap, 0, 0);
	tilemap_draw(bitmap, cliprect, atarigen_playfield_tilemap, 1, 1);
	tilemap_draw(bitmap, cliprect, atarigen_playfield_tilemap, 2, 2);
	tilemap_draw(bitmap, cliprect, atarigen_playfield_tilemap, 3, 3);

	/* draw and merge the MO */
	mobitmap = atarimo_render(machine, 0, cliprect, &rectlist);
	for (r = 0; r < rectlist.numrects; r++, rectlist.rect++)
		for (y = rectlist.rect->min_y; y <= rectlist.rect->max_y; y++)
		{
			UINT16 *mo = (UINT16 *)mobitmap->base + mobitmap->rowpixels * y;
			UINT16 *pf = (UINT16 *)bitmap->base + bitmap->rowpixels * y;
			UINT8 *pri = (UINT8 *)priority_bitmap->base + priority_bitmap->rowpixels * y;
			for (x = rectlist.rect->min_x; x <= rectlist.rect->max_x; x++)
				if (mo[x])
				{
					/* not verified: logic is all controlled in a PAL

                        factors: LBPRI1-0, LBPIX3, ANPIX1-0, PFPIX3, PFPRI1-0,
                                 (~LBPIX3 & ~LBPIX2 & ~LBPIX1 & ~LBPIX0)
                    */

					/* only draw if not high priority PF */
					if (!pri[x] || !(pf[x] & 8))
						pf[x] = mo[x];

					/* erase behind ourselves */
					mo[x] = 0;
				}
		}

	/* add the alpha on top */
	tilemap_draw(bitmap, cliprect, atarigen_alpha_tilemap, 0, 0);
	return 0;
}
