summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/video/taitosj.cpp
blob: 69f6896e82ed5d62e100787a02c75dd3064b17cf (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                    







                                                                            
                
                         
                             
 
 



                                                                      
                                      
 
 
 

                                                             


                                                                            
                                                                           






                                                                       
                                                             
                                                        
                                                                




























                                                                             










                                                                            
                                               

                                               
                                                 

                                                 
                                                




                                                                            
                              
 

                                                             
              
 
                                                       
                                              


                                                        
 
                                  
         

                                     

                                   
                                                    

                                          
                                                    
                                          
                                                                  

                                     
                                                    


                                          
                                                                  

                                    
                                                    


                                          
                                                                  
 
                                                            
         

 




                                                                            
 
                                        

              
                                                         






                                                                                          
                                                                                                 


                                                                                    






                                                                               
                                                                                                    
                                                                                                                                  
                                                  




                 
                                 


              
                                                   


                               

                                                                                

         

                                                    
 



                                                                 
 
                             



 
                                             
 
                    
 
                                                               

                          
                                                      

                        
 
                        
 

                                      
 
                   



 
                                                    
 
                                           


                                    

                                                                              


                    

                                                                              

                 
                                              


         
                                                     
 
                                                           

 
 
                                                           
 



                               

 
 
                                                                                
 
                                
 

                                                                       
 



                           
                                                                         


                                
                                                                                                 


 
                                                                                                            
 



                                                   



























                                                                
                                                                                 
                                                         
                                                                                                                            
                                                                               
                          

                                                                               
                                     
 
                                                          
                                                                                                                            
                                                                               
                          

                                                                               
                                     
 
                                     
                                             

                                                                                             
                                                         




                 
                                                   
 
                       
         

                           
                                                
                                                         
                 
                                   
                                         
 
                                                                                                 
 
                                                                         

                                                                          
                         
                                                 
 
                                                                                                           
 
                                                                                 

                                                                                        

                                                                              
                                 

                                                
                                                                                                                           
 






                                                                                                        
                                         


                                                                       
                                                                                               





                                                                       
                                                                                               







                                         
                                                                                    
 
                  

                                        
 
                                              
         
                               
 
                                                                                         
 
                                                   
                 


                                                   
                                              

                                          




                                              

                                         



                                                                                    



                                                  
 





                                                         
                 


                                              


         
 
                                                                                    
 
                 
                                

                                            


                                                                 
 



                                                 
 

                                                                                             
 
                                                                   
                                                         
                                                                                                                 
                                                                              
                          
                                       
                               
 
                                     
                                             
                                                                                                                                           
                         
                                                                                                                    
                                                                                    
 
                                                                                                                    

                                                                                    
                                                                                                                    
                                                                                    
                         
 


                      
 
                                                                                          
 






                                                      
                                                                                                 

                                              
                                                                                                         


                 

 
                                 


                    


                                                
 







                                                
                                                                                                                         

                                                      
                                                            
                                             
 
                                                                                                                         

                                                             
                                                            
                                             
 
                                                                                                                         

                                                      
                                                            
                                             



         
                                                      
 
          




                                                                                      

                                                                            
 
                       


                           
                                                                                                               
                                                          
                 
                                       
 
                                                                                                          
                                                
 
                                                                                                 
 
                                                           
                         



                                                                                                                                                

                                                  

                                                      
                                                         
                                 

                                                  

                                                      
                                                         

                                 
                                                                                                                                                      
                                                                          

                                                                                                          
                                                                                                                                                      
                                                                                  





                         
                                                                                                                                           
 

                                                   
 
                                                     
         
                                            
 
                                              
 

                                                                                                      
                    
                                                                                                      
 
                                  
                                              
                                                                                                          
                    
                                              
                                                                                                          
 
                                                                                                                           
 

                                                                                             

                                                                                       

                                          
                                                                                                                                                      



                 
 
                                                                                                                                            
 
                                                     
         
                                                
 
                                                         
                                          
                                              
                                 
                                                                       

                                                                                                                                           
                                 
                            
                                              
                                 
                                                              

                                                                                                                                              
                                 
 

                                                                                                                               


                                                                                             

                                                                                       

                                          
                                                                                                                                                          




                 
                                                                                                                                                                      
 
                       
                                     
            
                                                                                                


 
                                                                                                                                                            
 
                  
 
                                                       
                                                           
 
                               
         
                                                                      
 
                                                                                               
         
 
 
 
                                                                             
 
                                        
 
                                                               
 
                                                                     
 
 
 
                                                                                                                          
 

                                                                                
 
                   
 
                      
 
                                                         
 
                                                                                 
 
                                                                                                          
                                                  
 

                 
 
 
                                                                                                                     
 
                                                                                         
 
 
 
                                                                                                                      
 
                                                                                          
 
// license:BSD-3-Clause
// copyright-holders:Nicola Salmoria
/***************************************************************************

  video.c

  Functions to emulate the video hardware of the machine.

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

#include "emu.h"
#include "video/resnet.h"
#include "includes/taitosj.h"


#define GLOBAL_FLIP_X           (*m_video_mode & 0x01)
#define GLOBAL_FLIP_Y           (*m_video_mode & 0x02)
#define SPRITE_RAM_PAGE_OFFSET  ((*m_video_mode & 0x04) ? 0x80 : 0x00)
#define SPRITES_ON              (*m_video_mode & 0x80)
#define TRANSPARENT_PEN         (0x40)



static const int layer_enable_mask[3] = { 0x10, 0x20, 0x40 };


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

  I call the three layers with the conventional names "front", "middle" and
  "back", because that's their default order, but they can be arranged,
  together with the sprites, in any order. The priority is selected by
  register 0xd300, which works as follow:

  bits 0-3 go to A4-A7 of a 256x4 PROM
  bit 4 selects D0/D1 or D2/D3 of the PROM
  bit 5-7 n.c.
  A0-A3 of the PROM is fed with a mask of the inactive layers
  (i.e. all-zero) in the order sprites-front-middle-back
  the 2-bit code which comes out from the PROM selects the layer
  to display.

  Here is a dump of one of these PROMs; on the right is the resulting order
  (s = sprites f = front m = middle b = back). Note that, in theory, the
  PROM could encode some really funky priority schemes which couldn't be
  reconducted to the simple layer order given here. Luckily, none of the
  games seem to do that. Actually, all of them seem to use the same PROM,
  with the exception of Wild Western.

                                                        d300 pri    d300 pri
  00: 08 09 08 0A 00 05 00 0F 08 09 08 0A 00 05 00 0F |  00  sfmb    10  msfb
  10: 08 09 08 0B 00 0D 00 0F 08 09 08 0A 00 05 00 0F |  01  sfbm    11  msbf
  20: 08 0A 08 0A 04 05 00 0F 08 0A 08 0A 04 05 00 0F |  02  smfb    12  mfsb
  30: 08 0A 08 0A 04 07 0C 0F 08 0A 08 0A 04 05 00 0F |  03  smbf    13  mfbs
  40: 08 0B 08 0B 0C 0F 0C 0F 08 09 08 0A 00 05 00 0F |  04  sbfm    14  mbsf
  50: 08 0B 08 0B 0C 0F 0C 0F 08 0A 08 0A 04 05 00 0F |  05  sbmf    15  mbfs
  60: 0D 0D 0C 0E 0D 0D 0C 0F 01 05 00 0A 01 05 00 0F |  06  fsmb    16  bsfm
  70: 0D 0D 0C 0F 0D 0D 0C 0F 01 09 00 0A 01 05 00 0F |  07  fsbm    17  bsmf
  80: 0D 0D 0E 0E 0D 0D 0C 0F 05 05 02 0A 05 05 00 0F |  08  fmsb    18  bfsm
  90: 0D 0D 0E 0E 0D 0D 0F 0F 05 05 0A 0A 05 05 00 0F |  09  fmbs    19  bfms
  A0: 0D 0D 0F 0F 0D 0D 0F 0F 09 09 08 0A 01 05 00 0F |  0A  fbsm    1A  bmsf
  B0: 0D 0D 0F 0F 0D 0D 0F 0F 09 09 0A 0A 05 05 00 0F |  0B  fbms    1B  bmfs
  C0: 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F |  0C   -      1C   -
  D0: 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F |  0D   -      1D   -
  E0: 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F |  0E   -      1E   -
  F0: 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F |  0F   -      1F   -

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



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

  Convert the color PROMs into a more useable format.

  The Taito games don't have a color PROM. They use RAM to dynamically
  create the palette. The resolution is 9 bit (3 bits per gun).

  The RAM is connected to the RGB output this way:

  bit 0 -- inverter -- 270 ohm resistor  -- RED
  bit 7 -- inverter -- 470 ohm resistor  -- RED
        -- inverter -- 1  kohm resistor  -- RED
        -- inverter -- 270 ohm resistor  -- GREEN
        -- inverter -- 470 ohm resistor  -- GREEN
        -- inverter -- 1  kohm resistor  -- GREEN
        -- inverter -- 270 ohm resistor  -- BLUE
        -- inverter -- 470 ohm resistor  -- BLUE
  bit 0 -- inverter -- 1  kohm resistor  -- BLUE

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

void taitosj_state::set_pens()
{
	static const int resistances[3] = { 1000, 470, 270 };
	double rweights[3], gweights[3], bweights[3];
	int i;

	/* compute the color output resistor weights */
	compute_resistor_weights(0, 255, -1.0,
			3, resistances, rweights, 0, 0,
			3, resistances, gweights, 0, 0,
			3, resistances, bweights, 0, 0);

	for (i = 0; i < 0x40; i++)
	{
		int bit0, bit1, bit2;
		int r, g, b, val;

		/* red component */
		val = m_paletteram[(i << 1) | 0x01];
		bit0 = (~val >> 6) & 0x01;
		bit1 = (~val >> 7) & 0x01;
		val = m_paletteram[(i << 1) | 0x00];
		bit2 = (~val >> 0) & 0x01;
		r = combine_3_weights(rweights, bit0, bit1, bit2);

		/* green component */
		val = m_paletteram[(i << 1) | 0x01];
		bit0 = (~val >> 3) & 0x01;
		bit1 = (~val >> 4) & 0x01;
		bit2 = (~val >> 5) & 0x01;
		g = combine_3_weights(gweights, bit0, bit1, bit2);

		/* blue component */
		val = m_paletteram[(i << 1) | 0x01];
		bit0 = (~val >> 0) & 0x01;
		bit1 = (~val >> 1) & 0x01;
		bit2 = (~val >> 2) & 0x01;
		b = combine_3_weights(bweights, bit0, bit1, bit2);

		m_palette->set_pen_color(i, rgb_t(r, g, b));
	}
}

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

  Start the video hardware emulation.

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

void taitosj_state::compute_draw_order()
{
	int i;
	uint8_t *color_prom = memregion("proms")->base();

	/* do a simple conversion of the PROM into layer priority order. Note that */
	/* this is a simplification, which assumes the PROM encodes a sensible priority */
	/* scheme. */
	for (i = 0; i < 32; i++)
	{
		int j;
		int mask = 0;   /* start with all four layers active, so we'll get the highest */
						/* priority one in the first loop */
		for (j = 3; j >= 0; j--)
		{
			int data = color_prom[0x10 * (i & 0x0f) + mask] & 0x0f;

			if (i & 0x10)
				data = data >> 2;
			else
				data = data & 0x03;

			mask |= (1 << data);    /* in next loop, we'll see which of the remaining */
									/* layers has top priority when this one is transparent */
			m_draw_order[i][j] = data;
		}
	}
}


void taitosj_state::video_start()
{
	int i;

	m_sprite_layer_collbitmap1.allocate(16,16);

	for (i = 0; i < 3; i++)
	{
		m_screen->register_screen_bitmap(m_layer_bitmap[i]);
		m_screen->register_screen_bitmap(m_sprite_layer_collbitmap2[i]);
	}

	m_sprite_sprite_collbitmap1.allocate(32,32);
	m_sprite_sprite_collbitmap2.allocate(32,32);

	m_gfxdecode->gfx(0)->set_source(m_characterram);
	m_gfxdecode->gfx(1)->set_source(m_characterram);
	m_gfxdecode->gfx(2)->set_source(m_characterram + 0x1800);
	m_gfxdecode->gfx(3)->set_source(m_characterram + 0x1800);

	compute_draw_order();
}



READ8_MEMBER(taitosj_state::taitosj_gfxrom_r)
{
	uint8_t ret;

	offs_t offs = m_gfxpointer[0] | (m_gfxpointer[1] << 8);

	if (offs < 0x8000)
		ret = memregion("gfx1")->base()[offs];
	else
		ret = 0;

	offs = offs + 1;

	m_gfxpointer[0] = offs & 0xff;
	m_gfxpointer[1] = offs >> 8;

	return ret;
}



WRITE8_MEMBER(taitosj_state::taitosj_characterram_w)
{
	if (m_characterram[offset] != data)
	{
		if (offset < 0x1800)
		{
			m_gfxdecode->gfx(0)->mark_dirty((offset / 8) & 0xff);
			m_gfxdecode->gfx(1)->mark_dirty((offset / 32) & 0x3f);
		}
		else
		{
			m_gfxdecode->gfx(2)->mark_dirty((offset / 8) & 0xff);
			m_gfxdecode->gfx(3)->mark_dirty((offset / 32) & 0x3f);
		}

		m_characterram[offset] = data;
	}
}

WRITE8_MEMBER(taitosj_state::junglhbr_characterram_w)
{
	taitosj_characterram_w(space, offset, data ^ 0xfc);
}


WRITE8_MEMBER(taitosj_state::taitosj_collision_reg_clear_w)
{
	m_collision_reg[0] = 0;
	m_collision_reg[1] = 0;
	m_collision_reg[2] = 0;
	m_collision_reg[3] = 0;
}


inline int taitosj_state::get_sprite_xy(uint8_t which, uint8_t* sx, uint8_t* sy)
{
	offs_t offs = which * 4;

	*sx =       m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 0] - 1;
	*sy = 240 - m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 1];

	return (*sy < 240);
}


inline gfx_element * taitosj_state::get_sprite_gfx_element(uint8_t which)
{
	offs_t offs = which * 4;

	return m_gfxdecode->gfx((m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 3] & 0x40) ? 3 : 1);
}


int taitosj_state::check_sprite_sprite_bitpattern(int sx1, int sy1, int which1,int sx2, int sy2, int which2)
{
	int x, y, minx, miny, maxx = 16, maxy = 16;

	offs_t offs1 = which1 * 4;
	offs_t offs2 = which2 * 4;

	/* normalize coordinates to (0,0) and compute overlap */
	if (sx1 < sx2)
	{
		sx2 -= sx1;
		sx1 = 0;
		minx = sx2;
	}
	else
	{
		sx1 -= sx2;
		sx2 = 0;
		minx = sx1;
	}

	if (sy1 < sy2)
	{
		sy2 -= sy1;
		sy1 = 0;
		miny = sy2;
	}
	else
	{
		sy1 -= sy2;
		sy2 = 0;
		miny = sy1;
	}

	/* draw the sprites into separate bitmaps and check overlapping region */
	m_sprite_layer_collbitmap1.fill(TRANSPARENT_PEN);
		get_sprite_gfx_element(which1)->transpen(m_sprite_sprite_collbitmap1,m_sprite_sprite_collbitmap1.cliprect(),
			m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs1 + 3] & 0x3f,
			0,
			m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs1 + 2] & 0x01,
			m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs1 + 2] & 0x02,
			sx1, sy1, 0);

	m_sprite_sprite_collbitmap2.fill(TRANSPARENT_PEN);
		get_sprite_gfx_element(which2)->transpen(m_sprite_sprite_collbitmap2,m_sprite_sprite_collbitmap2.cliprect(),
			m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs2 + 3] & 0x3f,
			0,
			m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs2 + 2] & 0x01,
			m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs2 + 2] & 0x02,
			sx2, sy2, 0);

	for (y = miny; y < maxy; y++)
		for (x = minx; x < maxx; x++)
			if ((m_sprite_sprite_collbitmap1.pix16(y, x) != TRANSPARENT_PEN) &&
				(m_sprite_sprite_collbitmap2.pix16(y, x) != TRANSPARENT_PEN))
				return 1;  /* collided */

	return 0;
}


void taitosj_state::check_sprite_sprite_collision()
{
	if (SPRITES_ON)
	{
		int which1;

		/* chech each pair of sprites */
		for (which1 = 0; which1 < 0x20; which1++)
		{
			int which2;
			uint8_t sx1, sy1;

			if ((which1 >= 0x10) && (which1 <= 0x17)) continue; /* no sprites here */

			if (!get_sprite_xy(which1, &sx1, &sy1)) continue;

			for (which2 = which1 + 1; which2 < 0x20; which2++)
			{
				uint8_t sx2, sy2;

				if ((which2 >= 0x10) && (which2 <= 0x17)) continue;   /* no sprites here */

				if (!get_sprite_xy(which2, &sx2, &sy2)) continue;

				/* quickly rule out any pairs that cannot be touching */
				if ((abs((int8_t)sx1 - (int8_t)sx2) < 16) &&
					(abs((int8_t)sy1 - (int8_t)sy2) < 16))
				{
					int reg;

					if (!check_sprite_sprite_bitpattern(sx1, sy1, which1, sx2, sy2, which2))  continue;

					/* mark sprite as collided */
					/* note that only the sprite with the higher number is marked */
					/* as collided. This is how the hardware works and required */
					/* by Pirate Pete to be able to finish the last round. */

					/* the last sprite has to be moved at the start of the list */
					if (which2 == 0x1f)
					{
						reg = which1 >> 3;
						if (reg == 3)  reg = 2;

						m_collision_reg[reg] |= (1 << (which1 & 0x07));
					}
					else
					{
						reg = which2 >> 3;
						if (reg == 3)  reg = 2;

						m_collision_reg[reg] |= (1 << (which2 & 0x07));
					}
				}
			}
		}
	}
}


void taitosj_state::calculate_sprite_areas(int *sprites_on, rectangle *sprite_areas)
{
	int which;
	int width = m_screen->width();
	int height = m_screen->height();

	for (which = 0; which < 0x20; which++)
	{
		uint8_t sx, sy;

		if ((which >= 0x10) && (which <= 0x17)) continue;   /* no sprites here */

		if (get_sprite_xy(which, &sx, &sy))
		{
			int minx, miny, maxx, maxy;

			if (GLOBAL_FLIP_X)
				sx = 238 - sx;

			if (GLOBAL_FLIP_Y)
				sy = 242 - sy;

			minx = sx;
			miny = sy;

			maxx = minx + 15;
			maxy = miny + 15;

			/* check for bitmap bounds to avoid illegal memory access */
			if (minx < 0) minx = 0;
			if (miny < 0) miny = 0;
			if (maxx >= width - 1)
				maxx = width - 1;
			if (maxy >= height - 1)
				maxy = height - 1;

			sprite_areas[which].min_x = minx;
			sprite_areas[which].max_x = maxx;
			sprite_areas[which].min_y = miny;
			sprite_areas[which].max_y = maxy;

			sprites_on[which] = 1;
		}
		/* sprite is off */
		else
			sprites_on[which] = 0;
	}
}


int taitosj_state::check_sprite_layer_bitpattern(int which, rectangle *sprite_areas)
{
	int y, x;
	offs_t offs = which * 4;
	int result = 0;  /* no collisions */

	int check_layer_1 = *m_video_mode & layer_enable_mask[0];
	int check_layer_2 = *m_video_mode & layer_enable_mask[1];
	int check_layer_3 = *m_video_mode & layer_enable_mask[2];

	int minx = sprite_areas[which].min_x;
	int miny = sprite_areas[which].min_y;
	int maxx = sprite_areas[which].max_x + 1;
	int maxy = sprite_areas[which].max_y + 1;

	int flip_x = (m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 2] & 0x01) ^ GLOBAL_FLIP_X;
	int flip_y = (m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 2] & 0x02) ^ GLOBAL_FLIP_Y;

	/* draw sprite into a bitmap and check if layers collide */
	m_sprite_layer_collbitmap1.fill(TRANSPARENT_PEN);
	get_sprite_gfx_element(which)->transpen(m_sprite_layer_collbitmap1,m_sprite_layer_collbitmap1.cliprect(),
			m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 3] & 0x3f,
			0,
			flip_x, flip_y,
			0,0,0);

	for (y = miny; y < maxy; y++)
		for (x = minx; x < maxx; x++)
			if (m_sprite_layer_collbitmap1.pix16(y - miny, x - minx) != TRANSPARENT_PEN) /* is there anything to check for ? */
			{
				if (check_layer_1 && (m_sprite_layer_collbitmap2[0].pix16(y, x) != TRANSPARENT_PEN))
					result |= 0x01;  /* collided with layer 1 */

				if (check_layer_2 && (m_sprite_layer_collbitmap2[1].pix16(y, x) != TRANSPARENT_PEN))
					result |= 0x02;  /* collided with layer 2 */

				if (check_layer_3 && (m_sprite_layer_collbitmap2[2].pix16(y, x) != TRANSPARENT_PEN))
					result |= 0x04;  /* collided with layer 3 */
			}

	return result;
}


void taitosj_state::check_sprite_layer_collision(int *sprites_on, rectangle *sprite_areas)
{
	if (SPRITES_ON)
	{
		int which;

		/* check each sprite */
		for (which = 0; which < 0x20; which++)
		{
			if ((which >= 0x10) && (which <= 0x17)) continue;   /* no sprites here */

			if (sprites_on[which])
				m_collision_reg[3] |= check_sprite_layer_bitpattern(which, sprite_areas);
		}
	}
}


void taitosj_state::draw_layers()
{
	offs_t offs;

	m_layer_bitmap[0].fill(TRANSPARENT_PEN);
	m_layer_bitmap[1].fill(TRANSPARENT_PEN);
	m_layer_bitmap[2].fill(TRANSPARENT_PEN);

	for (offs = 0; offs < 0x0400; offs++)
	{
		int sx = offs % 32;
		int sy = offs / 32;

		if (GLOBAL_FLIP_X) sx = 31 - sx;
		if (GLOBAL_FLIP_Y) sy = 31 - sy;

		m_gfxdecode->gfx(m_colorbank[0] & 0x08 ? 2 : 0)->transpen(m_layer_bitmap[0],m_layer_bitmap[0].cliprect(),
				m_videoram_1[offs],
				m_colorbank[0] & 0x07,
				GLOBAL_FLIP_X,GLOBAL_FLIP_Y,
				8*sx,8*sy,0);

		m_gfxdecode->gfx(m_colorbank[0] & 0x80 ? 2 : 0)->transpen(m_layer_bitmap[1],m_layer_bitmap[1].cliprect(),
				m_videoram_2[offs],
				(m_colorbank[0] >> 4) & 0x07,
				GLOBAL_FLIP_X,GLOBAL_FLIP_Y,
				8*sx,8*sy,0);

		m_gfxdecode->gfx(m_colorbank[1] & 0x08 ? 2 : 0)->transpen(m_layer_bitmap[2],m_layer_bitmap[2].cliprect(),
				m_videoram_3[offs],
				m_colorbank[1] & 0x07,
				GLOBAL_FLIP_X,GLOBAL_FLIP_Y,
				8*sx,8*sy,0);
	}
}


void taitosj_state::draw_sprites(bitmap_ind16 &bitmap)
{
	/*
	   sprite visibility area is missing 4 pixels from the sides, surely to reduce
	   wraparound side effects. This was verified on a real Elevator Action.
	   Note that the clipping is asymmetrical. This matches the real thing.
	   I'm not sure of what should happen when the screen is flipped, though.
	 */
	const rectangle spritevisiblearea(0*8+3, 32*8-1-1, 2*8, 30*8-1);
	const rectangle spritevisibleareaflip(0*8+1, 32*8-3-1, 2*8, 30*8-1);

	if (SPRITES_ON)
	{
		int sprite;

		/* drawing order is a bit strange. The last sprite has to be moved at the start of the list. */
		for (sprite = 0x1f; sprite >= 0; sprite--)
		{
			uint8_t sx, sy;

			int which = (sprite - 1) & 0x1f;    /* move last sprite at the head of the list */
			offs_t offs = which * 4;

			if ((which >= 0x10) && (which <= 0x17)) continue;   /* no sprites here */

			if (get_sprite_xy(which, &sx, &sy))
			{
				int code = m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 3] & 0x3f;
				int color = 2 * ((m_colorbank[1] >> 4) & 0x03) + ((m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 2] >> 2) & 0x01);
				int flip_x = m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 2] & 0x01;
				int flip_y = m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 2] & 0x02;

				if (GLOBAL_FLIP_X)
				{
					sx = 238 - sx;
					flip_x = !flip_x;
				}

				if (GLOBAL_FLIP_Y)
				{
					sy = 242 - sy;
					flip_y = !flip_y;
				}

				get_sprite_gfx_element(which)->transpen(bitmap,GLOBAL_FLIP_X ? spritevisibleareaflip : spritevisiblearea, code, color,
						flip_x, flip_y, sx, sy,0);

				/* draw with wrap around. The horizontal games (eg. sfposeid) need this */
				get_sprite_gfx_element(which)->transpen(bitmap,GLOBAL_FLIP_X ? spritevisibleareaflip : spritevisiblearea, code, color,
						flip_x, flip_y, sx - 0x100, sy,0);
			}
		}
	}
}


void taitosj_state::taitosj_copy_layer(bitmap_ind16 &bitmap, const rectangle &cliprect,int which, int *sprites_on, rectangle *sprite_areas)
{
	static const int fudge1[3] = { 3,  1, -1 };
	static const int fudge2[3] = { 8, 10, 12 };

	if (*m_video_mode & layer_enable_mask[which])
	{
		int i, scrollx, scrolly[32];

		scrollx = m_scroll[2 * which];

		if (GLOBAL_FLIP_X)
			scrollx =  (scrollx & 0xf8) + ((scrollx + fudge1[which]) & 7) + fudge2[which];
		else
			scrollx = -(scrollx & 0xf8) + ((scrollx + fudge1[which]) & 7) + fudge2[which];

		if (GLOBAL_FLIP_Y)
			for (i = 0;i < 32;i++)
				scrolly[31 - i] =  m_colscrolly[32 * which + i] + m_scroll[2 * which + 1];
		else
			for (i = 0;i < 32;i++)
				scrolly[i]      = -m_colscrolly[32 * which + i] - m_scroll[2 * which + 1];

		copyscrollbitmap_trans(bitmap, m_layer_bitmap[which], 1, &scrollx, 32, scrolly, cliprect, TRANSPARENT_PEN);

		/* store parts covered with sprites for sprites/layers collision detection */
		for (i = 0; i < 0x20; i++)
		{
			if ((i >= 0x10) && (i <= 0x17)) continue; /* no sprites here */

			if (sprites_on[i])
				copyscrollbitmap(m_sprite_layer_collbitmap2[which], m_layer_bitmap[which], 1, &scrollx, 32, scrolly, sprite_areas[i]);
		}
	}
}


void taitosj_state::kikstart_copy_layer(bitmap_ind16 &bitmap, const rectangle &cliprect,int which, int *sprites_on, rectangle *sprite_areas)
{
	if (*m_video_mode & layer_enable_mask[which])
	{
		int i, scrolly, scrollx[32 * 8];

		for (i = 1; i < 32*8; i++)  /* 1-255 ! */
			if (GLOBAL_FLIP_Y)
				switch (which)
				{
				case 0: scrollx[32 * 8 - i] = 0 ;break;
				case 1: scrollx[32 * 8 - i] = m_kikstart_scrollram[i] + ((m_scroll[2 * which] + 0x0a) & 0xff);break;
				case 2: scrollx[32 * 8 - i] = m_kikstart_scrollram[0x100 + i] + ((m_scroll[2 * which] + 0xc) & 0xff);break;
				}
			else
				switch (which)
				{
				case 0: scrollx[i] = 0 ;break;
				case 1: scrollx[i] = 0xff - m_kikstart_scrollram[i - 1] - ((m_scroll[2 * which] - 0x10) & 0xff);break;
				case 2: scrollx[i] = 0xff - m_kikstart_scrollram[0x100 + i - 1] - ((m_scroll[2 * which] - 0x12) & 0xff);break;
				}

		scrolly = m_scroll[2 * which + 1];   /* always 0 */
		copyscrollbitmap_trans(bitmap, m_layer_bitmap[which], 32 * 8, scrollx, 1, &scrolly, cliprect, TRANSPARENT_PEN);

		/* store parts covered with sprites for sprites/layers collision detection */
		for (i = 0; i < 0x20; i++)
		{
			if ((i >= 0x10) && (i <= 0x17)) continue; /* no sprites here */

			if (sprites_on[i])
				copyscrollbitmap(m_sprite_layer_collbitmap2[which], m_layer_bitmap[which], 32 * 8, scrollx, 1, &scrolly, sprite_areas[i]);
		}
	}
}


void taitosj_state::copy_layer(bitmap_ind16 &bitmap, const rectangle &cliprect,copy_layer_func_t copy_layer_func, int which, int *sprites_on, rectangle *sprite_areas)
{
	if (which == 0)
		draw_sprites(bitmap);
	else
		(this->*copy_layer_func)(bitmap, cliprect, which - 1, sprites_on, sprite_areas);
}


void taitosj_state::copy_layers(bitmap_ind16 &bitmap, const rectangle &cliprect,copy_layer_func_t copy_layer_func, int *sprites_on, rectangle *sprite_areas)
{
	int i = 0;

	/* fill the screen with the background color */
	bitmap.fill(8 * (m_colorbank[1] & 0x07), cliprect);

	for (i = 0; i < 4; i++)
	{
		int which = m_draw_order[*m_video_priority & 0x1f][i];

		copy_layer(bitmap, cliprect, copy_layer_func, which, sprites_on, sprite_areas);
	}
}


void taitosj_state::check_collision(int *sprites_on, rectangle *sprite_areas)
{
	check_sprite_sprite_collision();

	check_sprite_layer_collision(sprites_on, sprite_areas);

	/*check_layer_layer_collision();*/  /* not implemented !!! */
}


int taitosj_state::video_update_common(bitmap_ind16 &bitmap, const rectangle &cliprect, copy_layer_func_t copy_layer_func)
{
	int sprites_on[0x20];           /* 1 if sprite is active */
	rectangle sprite_areas[0x20];   /* areas on bitmap (sprite locations) */

	set_pens();

	draw_layers();

	calculate_sprite_areas(sprites_on, sprite_areas);

	copy_layers(bitmap, cliprect, copy_layer_func, sprites_on, sprite_areas);

	/*check_sprite_layer_collision() uses drawn bitmaps, so it must me called _AFTER_ draw_layers() */
	check_collision(sprites_on, sprite_areas);

	return 0;
}


uint32_t taitosj_state::screen_update_taitosj(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	return video_update_common(bitmap, cliprect, &taitosj_state::taitosj_copy_layer);
}


uint32_t taitosj_state::screen_update_kikstart(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	return video_update_common(bitmap, cliprect, &taitosj_state::kikstart_copy_layer);
}