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

   Dark Seal Video emulation - Bryan McPhail, mish@tendril.co.uk

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

Data East custom chip 55:  Generates two playfields, playfield 1 is underneath
playfield 2.  Dark Seal uses two of these chips.  1 playfield is _always_ off
in this game.

    16 bytes of control registers per chip.

    Word 0:
        Mask 0x0080: Flip screen
        Mask 0x007f: ?
    Word 2:
        Mask 0xffff: Playfield 2 X scroll (top playfield)
    Word 4:
        Mask 0xffff: Playfield 2 Y scroll (top playfield)
    Word 6:
        Mask 0xffff: Playfield 1 X scroll (bottom playfield)
    Word 8:
        Mask 0xffff: Playfield 1 Y scroll (bottom playfield)
    Word 0xa:
        Mask 0xc000: Playfield 1 shape??
        Mask 0x3000: Playfield 1 rowscroll style (maybe mask 0x3800??)
        Mask 0x0300: Playfield 1 colscroll style (maybe mask 0x0700??)?

        Mask 0x00c0: Playfield 2 shape??
        Mask 0x0030: Playfield 2 rowscroll style (maybe mask 0x0038??)
        Mask 0x0003: Playfield 2 colscroll style (maybe mask 0x0007??)?
    Word 0xc:
        Mask 0x8000: Playfield 1 is 8*8 tiles else 16*16
        Mask 0x4000: Playfield 1 rowscroll enabled
        Mask 0x2000: Playfield 1 colscroll enabled
        Mask 0x1f00: ?

        Mask 0x0080: Playfield 2 is 8*8 tiles else 16*16
        Mask 0x0040: Playfield 2 rowscroll enabled
        Mask 0x0020: Playfield 2 colscroll enabled
        Mask 0x001f: ?
    Word 0xe:
        ??

Locations 0 & 0xe are mostly unknown:

                             0      14
Caveman Ninja (bottom):     0053    1100 (changes to 1111 later)
Caveman Ninja (top):        0010    0081
Two Crude (bottom):         0053    0000
Two Crude (top):            0010    0041
Dark Seal (bottom):         0010    0000
Dark Seal (top):            0053    4101
Tumblepop:                  0010    0000
Super Burger Time:          0010    0000

Location 0xe looks like it could be a mirror of another byte..

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

Sprites - Data East custom chip 52

    8 bytes per sprite, unknowns bits seem unused.

    Word 0:
        Mask 0x8000 - ?
        Mask 0x4000 - Y flip
        Mask 0x2000 - X flip
        Mask 0x1000 - Sprite flash
        Mask 0x0800 - ?
        Mask 0x0600 - Sprite height (1x, 2x, 4x, 8x)
        Mask 0x01ff - Y coordinate

    Word 2:
        Mask 0xffff - Sprite number

    Word 4:
        Mask 0x8000 - ?
        Mask 0x4000 - Sprite is drawn beneath top 8 pens of playfield 4
        Mask 0x3e00 - Colour (32 palettes, most games only use 16)
        Mask 0x01ff - X coordinate

    Word 6:
        Always unused.

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

#include "emu.h"

UINT16 *darkseal_pf12_row,*darkseal_pf34_row;
UINT16 *darkseal_pf1_data,*darkseal_pf2_data,*darkseal_pf3_data;

static UINT16 darkseal_control_0[8];
static UINT16 darkseal_control_1[8];

static tilemap_t *pf1_tilemap,*pf2_tilemap,*pf3_tilemap;
static int flipscreen;

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

/* Function for all 16x16 1024x1024 layers */
static TILEMAP_MAPPER( darkseal_scan )
{
	/* logical (col,row) -> memory offset */
	return (col & 0x1f) + ((row & 0x1f) << 5) + ((col & 0x20) << 5) + ((row & 0x20) << 6);
}

INLINE void get_bg_tile_info(running_machine *machine,tile_data *tileinfo,int tile_index,int gfx_bank,UINT16 *gfx_base)
{
	int tile,color;

	tile=gfx_base[tile_index];
	color=tile >> 12;
	tile=tile&0xfff;

	SET_TILE_INFO(
			gfx_bank,
			tile,
			color,
			0);
}

static TILE_GET_INFO( get_bg_tile_info2 ) { get_bg_tile_info(machine,tileinfo,tile_index,1,darkseal_pf2_data); }
static TILE_GET_INFO( get_bg_tile_info3 ) { get_bg_tile_info(machine,tileinfo,tile_index,2,darkseal_pf3_data); }

static TILE_GET_INFO( get_fg_tile_info )
{
	int tile=darkseal_pf1_data[tile_index];
	int color=tile >> 12;

	tile=tile&0xfff;
	SET_TILE_INFO(
			0,
			tile,
			color,
			0);
}

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

static void update_24bitcol(running_machine *machine, int offset)
{
	int r,g,b;

	r = (machine->generic.paletteram.u16[offset] >> 0) & 0xff;
	g = (machine->generic.paletteram.u16[offset] >> 8) & 0xff;
	b = (machine->generic.paletteram2.u16[offset] >> 0) & 0xff;

	palette_set_color(machine,offset,MAKE_RGB(r,g,b));
}

WRITE16_HANDLER( darkseal_palette_24bit_rg_w )
{
	COMBINE_DATA(&space->machine->generic.paletteram.u16[offset]);
	update_24bitcol(space->machine, offset);
}

WRITE16_HANDLER( darkseal_palette_24bit_b_w )
{
	COMBINE_DATA(&space->machine->generic.paletteram2.u16[offset]);
	update_24bitcol(space->machine, offset);
}

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

static void draw_sprites(running_machine* machine, bitmap_t *bitmap, const rectangle *cliprect)
{
	UINT16 *buffered_spriteram16 = machine->generic.buffered_spriteram.u16;
	int offs;

	for (offs = 0;offs < 0x400;offs += 4)
	{
		int x,y,sprite,colour,multi,fx,fy,inc,flash,mult;

		sprite = buffered_spriteram16[offs+1] & 0x1fff;
		if (!sprite) continue;

		y = buffered_spriteram16[offs];
		x = buffered_spriteram16[offs+2];

		flash=y&0x1000;
		if (flash && (machine->primary_screen->frame_number() & 1)) continue;

		colour = (x >> 9) &0x1f;

		fx = y & 0x2000;
		fy = y & 0x4000;
		multi = (1 << ((y & 0x0600) >> 9)) - 1;	/* 1x, 2x, 4x, 8x height */

		x = x & 0x01ff;
		y = y & 0x01ff;
		if (x >= 256) x -= 512;
		if (y >= 256) y -= 512;
		x = 240 - x;
		y = 240 - y;

		if (x>256) continue; /* Speedup */

		sprite &= ~multi;
		if (fy)
			inc = -1;
		else
		{
			sprite += multi;
			inc = 1;
		}

		if (flipscreen)
		{
			y=240-y;
			x=240-x;
			if (fx) fx=0; else fx=1;
			if (fy) fy=0; else fy=1;
			mult=16;
		}
		else mult=-16;

		while (multi >= 0)
		{
			drawgfx_transpen(bitmap,cliprect,machine->gfx[3],
					sprite - multi * inc,
					colour,
					fx,fy,
					x,y + mult * multi,0);

			multi--;
		}
	}
}

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

WRITE16_HANDLER( darkseal_pf1_data_w )
{
	COMBINE_DATA(&darkseal_pf1_data[offset]);
	tilemap_mark_tile_dirty(pf1_tilemap,offset);
}

WRITE16_HANDLER( darkseal_pf2_data_w )
{
	COMBINE_DATA(&darkseal_pf2_data[offset]);
	tilemap_mark_tile_dirty(pf2_tilemap,offset);
}

WRITE16_HANDLER( darkseal_pf3_data_w )
{
	COMBINE_DATA(&darkseal_pf3_data[offset]);
	tilemap_mark_tile_dirty(pf3_tilemap,offset);
}

WRITE16_HANDLER( darkseal_pf3b_data_w ) /* Mirror */
{
	darkseal_pf3_data_w(space,offset+0x800,data,mem_mask);
}

WRITE16_HANDLER( darkseal_control_0_w )
{
	COMBINE_DATA(&darkseal_control_0[offset]);
}

WRITE16_HANDLER( darkseal_control_1_w )
{
	COMBINE_DATA(&darkseal_control_1[offset]);
}

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

VIDEO_START( darkseal )
{
	pf1_tilemap = tilemap_create(machine, get_fg_tile_info, tilemap_scan_rows, 8, 8,64,64);
	pf2_tilemap = tilemap_create(machine, get_bg_tile_info2,darkseal_scan,    16,16,64,64);
	pf3_tilemap = tilemap_create(machine, get_bg_tile_info3,darkseal_scan,         16,16,64,64);

	tilemap_set_transparent_pen(pf1_tilemap,0);
	tilemap_set_transparent_pen(pf2_tilemap,0);
}

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

VIDEO_UPDATE( darkseal )
{
	flipscreen=!(darkseal_control_0[0]&0x80);
	tilemap_set_flip_all(screen->machine,flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);

	/* Update scroll registers */
	tilemap_set_scrollx( pf1_tilemap,0, darkseal_control_1[3] );
	tilemap_set_scrolly( pf1_tilemap,0, darkseal_control_1[4] );
	tilemap_set_scrollx( pf2_tilemap,0, darkseal_control_1[1]);
	tilemap_set_scrolly( pf2_tilemap,0, darkseal_control_1[2] );

	if (darkseal_control_0[6]&0x4000) { /* Rowscroll enable */
		int offs,scrollx=darkseal_control_0[3];

		tilemap_set_scroll_rows(pf3_tilemap,512);
		for (offs = 0;offs < 512;offs++)
			tilemap_set_scrollx( pf3_tilemap,offs, scrollx + darkseal_pf34_row[offs+0x40] );
	}
	else {
		tilemap_set_scroll_rows(pf3_tilemap,1);
		tilemap_set_scrollx( pf3_tilemap,0, darkseal_control_0[3] );
	}
	tilemap_set_scrolly( pf3_tilemap,0, darkseal_control_0[4] );

	tilemap_draw(bitmap,cliprect,pf3_tilemap,0,0);
	tilemap_draw(bitmap,cliprect,pf2_tilemap,0,0);
	draw_sprites(screen->machine,bitmap,cliprect);
	tilemap_draw(bitmap,cliprect,pf1_tilemap,0,0);
	return 0;
}

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