/*************************************************************
 *                                                           *
 * Signetics 2636 video chip                                 *
 *                                                           *
 *************************************************************

 PVI REGISTER DESCRIPTION
 ------------------------

       |              bit              |R/W| description
 byte  | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |   |
       |                               |   |
 FC0   | size 4| size 3| size 2| size 1| W | size of the 4 objects(=sprites)
       |                               |   |
 FC1   |       |C1 |C2 |C3 |C1 |C2 |C3 | W | colours of the 4 objects
       |       |  colour 1 |  colour 2 |   |
 FC2   |       |C1 |C2 |C3 |C1 |C2 |C3 | W |
       |       |  colour 3 |  colour 4 |   |
       |                               |   |
 FC3   |                       |sh |pos| W | 1=shape 0=position
       |                               |   | display format and position
 FC4   |            (free)             |   |
 FC5   |            (free)             |   |
       |                               |   |
 FC6   |   |C1 |C2 |C3 |BG |scrn colr  | W | background lock and colour
       |   |backg colr |enb|C1 |C2 |C3 |   | 3="enable"
       |                               |   |
 FC7   |            sound              | W | squarewave output
       |                               |   |
 FC8   |       N1      |      N2       | W | range of the 4 display digits
 FC9   |       N3      |      N4       | W |
       |                               |   |
       |obj/backgrnd   |complete object| R |
 FCA   | 1 | 2 | 3 | 4 | 1 | 2 | 3 | 4 |   |
       |                               |   |
 FCB   |   |VR-|   object collisions   | R | Composition of object and back-
       |   |LE |1/2|1/3|1/3|1/4|2/4|3/4|   | ground,collision detection and
       |                               |   | object display as a state display
       |                               |   | for the status register.Set VRLE.
       |                               |   | wait for VRST.Read out or transmit
       |                               |   | [copy?] all bits until reset by
       |                               |   | VRST.
       |                               |   |
 FCC   |            PORT1              | R | PORT1 and PORT2 for the range of
 FCD   |            PORT2              |   | the A/D conversion.Cleared by VRST
 FCE   |            (free)             |   |
 FCF   |            (free)             |   |


 Size control by byte FC0

  bit  matrix
 |0|0|  8x10
 |0|1| 16x20
 |1|0| 32x40
 |1|1| 64x80

 CE1 and not-CE2 are outputs from the PVI.$E80..$EFF also controls the
 analogue multiplexer.


 SPRITES
 -------

 each object field: (=sprite data structure)

 0 \ 10 bytes of bitmap (Each object is 8 pixels wide.)
 9 /
 A   HC  horizontal object coordinate
 B   HCB horizontal dublicate coordinate
 C   VC  vertical object coordinate
 D   VCB vertical dublicate coordinate

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

#include "driver.h"
#include "s2636.h"

static const int SpriteOffset[4] = {0,0x10,0x20,0x40};

/* To adjust sprites against bitmap */

UINT8 *s2636_1_ram;
UINT8 *s2636_2_ram;
UINT8 *s2636_3_ram;

mame_bitmap *s2636_1_bitmap;
mame_bitmap *s2636_2_bitmap;
mame_bitmap *s2636_3_bitmap;

UINT8 s2636_1_dirty[4];
UINT8 s2636_2_dirty[4];
UINT8 s2636_3_dirty[4];

int s2636_x_offset=0;
int s2636_y_offset=0;

void s2636_w(UINT8 *workram,int offset,int data,UINT8 *dirty)
{
	if (workram[offset] != data)
    {
        workram[offset] = data;

        if(offset < 10)
			dirty[0]=1;
        else
        {
	        if((offset > 15) && (offset < 26))
				dirty[1]=1;
            else
            {
		        if((offset > 31) && (offset < 42))
					dirty[2]=1;
                else
                {
			        if((offset > 63) && (offset < 74))
						dirty[3]=1;
                }
            }
        }
    }
}

/*****************************************/
/* Check for Collision between 2 sprites */
/*****************************************/

static int SpriteCheck(running_machine *machine, int first,int second,UINT8 *workram,int Graphics_Bank,mame_bitmap *collision_bitmap)
{
	int Checksum=0;
	int x,y;

    // Does not check shadow sprites yet

    if((workram[SpriteOffset[first] + 10] != 0xff) && (workram[SpriteOffset[second] + 10] != 0xff))
    {
    	int fx1 = workram[SpriteOffset[first] + 10] + s2636_x_offset;
        int fy1 = workram[SpriteOffset[first] + 12] + s2636_y_offset;
		int fx2 = workram[SpriteOffset[second] + 10] + s2636_x_offset;
		int fy2 = workram[SpriteOffset[second] + 12] + s2636_y_offset;

        if((fx1>=0) && (fy1>=0) && (fx2>=0) && (fy2>=0))
		{
  		    int expand1 = 1 << (16+((workram[0xC0]>>(first<<1)) & 3));
  		    int expand2 = 1 << (16+((workram[0xC0]>>(second<<1)) & 3));

    	    int char1   = SpriteOffset[first]>>4;
    	    int char2   = SpriteOffset[second]>>4;

            /* Draw first sprite */

		    drawgfxzoom(collision_bitmap,machine->gfx[Graphics_Bank],
		                char1,
			            1,
		                0,0,
		                fx1,fy1,
		                &machine->screen[0].visarea, TRANSPARENCY_PEN, 0,
				        expand1,expand1);

            /* Get fingerprint */

	        for (x = fx1; x < fx1 + machine->gfx[Graphics_Bank]->width; x++)
	        {
		        for (y = fy1; y < fy1 + machine->gfx[Graphics_Bank]->height; y++)
                {
			        if ((x < machine->screen[0].visarea.min_x) ||
			            (x > machine->screen[0].visarea.max_x) ||
			            (y < machine->screen[0].visarea.min_y) ||
			            (y > machine->screen[0].visarea.max_y))
			        {
				        continue;
			        }

        	        Checksum += *BITMAP_ADDR8(collision_bitmap, y, x);
                }
	        }

            /* Blackout second sprite */

		    drawgfxzoom(collision_bitmap,machine->gfx[Graphics_Bank],
		                char2,
			            0,
		                0,0,
				        fx2,fy2,
		                &machine->screen[0].visarea, TRANSPARENCY_PEN, 0,
				        expand2,expand2);

            /* Remove fingerprint */

	        for (x = fx1; x < fx1 + machine->gfx[Graphics_Bank]->width; x++)
	        {
		        for (y = fy1; y < fy1 + machine->gfx[Graphics_Bank]->height; y++)
                {
			        if ((x < machine->screen[0].visarea.min_x) ||
			            (x > machine->screen[0].visarea.max_x) ||
			            (y < machine->screen[0].visarea.min_y) ||
			            (y > machine->screen[0].visarea.max_y))
			        {
				        continue;
			        }

        	        Checksum -= *BITMAP_ADDR8(collision_bitmap, y, x);
                }
	        }

            /* Zero bitmap */

		    drawgfxzoom(collision_bitmap,machine->gfx[Graphics_Bank],
		                char1,
			            0,
		                0,0,
		                fx1,fy1,
		                &machine->screen[0].visarea, TRANSPARENCY_PEN, 0,
				        expand1,expand1);
            }
    }

	return Checksum;
}

void s2636_update_bitmap(running_machine *machine,mame_bitmap *bitmap,UINT8 *workram,UINT8 *dirty,int Graphics_Bank,mame_bitmap *collision_bitmap)
{
	int CollisionSprite = 0;
    int spriteno;
    int offs;

    for(spriteno=0;spriteno<4;spriteno++)
    {
    	offs = SpriteOffset[spriteno];

    	if(workram[offs+10]!=0xFF)
		{
			int charno   = offs>>4;
	  		int expand   = 1 << (16+((workram[0xC0]>>(spriteno<<1)) & 3));
            int bx       = workram[offs+10] + s2636_x_offset;
            int by       = workram[offs+12] + s2636_y_offset;

            if((bx >= 0) && (by >= 0))
            {
                /* Get colour and mask correct bits */

                int colour   = workram[0xC1 + (spriteno >> 1)];

                if((spriteno & 1)==0) colour >>= 3;

                colour = (colour & 7) + 7;

                if(dirty[spriteno])
                {
	   			    decodechar(machine->gfx[Graphics_Bank],charno,workram,machine->drv->gfxdecodeinfo[Graphics_Bank].gfxlayout);
                    dirty[spriteno] = 0;
                }

		        drawgfxzoom(bitmap,machine->gfx[Graphics_Bank],
			                charno,
				            colour,
			                0,0,
			                bx,by,
			                &machine->screen[0].visarea,
							TRANSPARENCY_BLEND_RAW, 0,
					        expand,expand);

                /* Shadow Sprites */

                if((workram[offs+11]!=0xff) && (workram[offs+13]!=0xfe))
                {
            	    bx=workram[offs+11] + s2636_x_offset;

                    if(bx >= 0)
                    {
	            	    for(;by < 255;)
					    {
						    by=by+10+workram[offs+13];

				            drawgfxzoom(bitmap,machine->gfx[Graphics_Bank],
					                    charno,
						                colour,
				    	                0,0,
				        	            bx,by,
				            	        &machine->screen[0].visarea,
										TRANSPARENCY_BLEND_RAW, 0,
						        	    expand,expand);
	                    }
                    }
                }
            }
        }
    }

    /* Sprite->Sprite collision detection */

    if(SpriteCheck(machine,0,1,workram,Graphics_Bank,collision_bitmap)) CollisionSprite |= 0x20;
    if(SpriteCheck(machine,0,2,workram,Graphics_Bank,collision_bitmap)) CollisionSprite |= 0x10;
    if(SpriteCheck(machine,0,3,workram,Graphics_Bank,collision_bitmap)) CollisionSprite |= 0x08;
    if(SpriteCheck(machine,1,2,workram,Graphics_Bank,collision_bitmap)) CollisionSprite |= 0x04;
    if(SpriteCheck(machine,1,3,workram,Graphics_Bank,collision_bitmap)) CollisionSprite |= 0x02;
    if(SpriteCheck(machine,2,3,workram,Graphics_Bank,collision_bitmap)) CollisionSprite |= 0x01;

    workram[0xCB] = CollisionSprite;
}
