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



                                                    
                                                                                
 




                                                                                                 
 



                                                                                                                                                                                  






                           
                                                                                                                           



                                                                                                                          














                                                                                        

                                                                       



                                       
                        
                 

                                                                                                      
                                                                                                                         
                                                                                      

                                                                                                 


                                                                               

                                                                                      
 

                                                                   



                                                 
                                          
                                 
                                                                                      






                                                         
                                          
                                 
                                                                                  






                                                    
                                                    
                                                 
                                                                     
                                                     
                                                                    
                                 
                                                    
                                                
                                                                     
                                                     
                                                               
                                 
                                                        
                                                  
                                                                         

                                                     
                                                        
                                                   
                                                                         


                                                     
                                            
                                                                                
                                                                                         
                                                                    
                                         
                                                                             
                                                 
                                                                                                                         


                                                                                           
                                                                                                                              
                                                                     
                                                         
                                                                                         
                                                             
                                                                                                   
                                                                              
                                                                 
                                                                                       
                                                                     
                                                                                 

                                                                               
                                                                                                                  

                                                                                  
                                                                                                                  










                                                                                             



                                                            
                                                                                             
                                                                 
                                                                                                           
                                                                                      
                                                                         
                                                                                                   
                                                                                 
                                                                                                                                     
























                                                                                                                         

                                                                       



                 
                                                                                                                                      
 

                                                    
         
                                                    
         
                                              








                                                         
                                                       










                                                       

                                                                       
                 


                                                                                 
 

                                                                       
 
                                                               
 
                                                 
                         








                                                                                                    
                                 
                                                                               
 

                                                                                                                                   












                                                                                   
                                                      



                                 
                    
 
                                                                                                                                   







                                             
                                 




















                                      

                                         
         
                                                    
         
                                            
         









                                                                 
                 







                                                                                                                                

                                     
                                                         


                                                                 
                                       
                         
                                                 
                                 
                                                                   
                                 
                                                 
                                 
                                                                   



                                                                   
                                                                                                                 









                                               
                                      


                             
                              
// license:BSD-3-Clause
// copyright-holders:David Haywood, Phil Stroffolino

/*
    Namco System 2 Sprites - found on Namco System 2 video board (standard type)

    based on namcoic.txt this probably consists of the following
    C106 - Generates memory output clocks to generate X-Axis Zoom for Line Buffer Writes
    C134 - Object Memory Address Generator. Sequences the sprite memory contents to the hardware.
    C135 - Checks is object is displayed on Current output line.
    C146 - Steers the Decode Object Pixel data to the correct line buffer A or B

    Metal Hawk requires a different draw function, so might use a different chip unless the hookup is just scrambled (needs checking)

    used by the following drivers
    namcos2.cpp (all games EXCEPT Steel Gunner, Steel Gunner 2, Lucky & Wild, Suzuka 8 Hours, Suzuka 8 Hours 2 which use the newer Namco NB1 style sprites, see namco_c355spr.cpp)


*/

#include "emu.h"
#include "namcos2_sprite.h"

DEFINE_DEVICE_TYPE(NAMCOS2_SPRITE, namcos2_sprite_device, "namcos2_sprite", "Namco System 2 Sprites (C106,C134,C135,C146)")

namcos2_sprite_device::namcos2_sprite_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
	device_t(mconfig, NAMCOS2_SPRITE, tag, owner, clock),
	m_gfxdecode(*this, finder_base::DUMMY_TAG),
	m_spriteram(*this, finder_base::DUMMY_TAG)
{
}

void namcos2_sprite_device::device_start()
{
}

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

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

void namcos2_sprite_device::zdrawgfxzoom(
		screen_device &screen,
		bitmap_ind16 &dest_bmp,const rectangle &clip,gfx_element *gfx,
		u32 code,u32 color,bool flipx,bool flipy,int sx,int sy,
		int scalex, int scaley, int zpos)
{
	if (!scalex || !scaley) return;
	if (dest_bmp.bpp() == 16)
	{
		if (gfx)
		{
			device_palette_interface &palette = gfx->palette();
			const int shadow_offset = (palette.shadows_enabled()) ? palette.entries() : 0;
			const pen_t *pal = &palette.pen(gfx->colorbase() + gfx->granularity() * (color % gfx->colors()));
			const u8 *source_base = gfx->get_data(code % gfx->elements());
			const int sprite_screen_height = (scaley * gfx->height() + 0x8000) >> 16;
			const int sprite_screen_width = (scalex * gfx->width() + 0x8000) >> 16;
			if (sprite_screen_width && sprite_screen_height)
			{
				/* compute sprite increment per screen pixel */
				int dx = (gfx->width() << 16) / sprite_screen_width;
				int dy = (gfx->height() << 16) / sprite_screen_height;

				int ex = sx + sprite_screen_width;
				int ey = sy + sprite_screen_height;

				int x_index_base;
				int y_index;

				if (flipx)
				{
					x_index_base = (sprite_screen_width - 1) * dx;
					dx = -dx;
				}
				else
				{
					x_index_base = 0;
				}

				if (flipy)
				{
					y_index = (sprite_screen_height - 1) * dy;
					dy = -dy;
				}
				else
				{
					y_index = 0;
				}

				if (sx < clip.min_x)
				{ /* clip left */
					int pixels = clip.min_x - sx;
					sx += pixels;
					x_index_base += pixels * dx;
				}
				if (sy < clip.min_y)
				{ /* clip top */
					int pixels = clip.min_y - sy;
					sy += pixels;
					y_index += pixels * dy;
				}
				if (ex > clip.max_x + 1)
				{ /* clip right */
					int pixels = ex - clip.max_x - 1;
					ex -= pixels;
				}
				if (ey > clip.max_y + 1)
				{ /* clip bottom */
					int pixels = ey - clip.max_y - 1;
					ey -= pixels;
				}

				if (ex > sx)
				{ /* skip if inner loop doesn't draw anything */
					bitmap_ind8 &priority_bitmap = screen.priority();
					if (priority_bitmap.valid())
					{
						for (int y = sy; y < ey; y++)
						{
							const u8 *source = source_base + (y_index>>16) * gfx->rowbytes();
							u16 *dest = &dest_bmp.pix16(y);
							u8 *pri = &priority_bitmap.pix8(y);
							int x_index = x_index_base;
							/* this code was previously shared with the c355 where this was needed
							if (m_palxor)
							{
							    for (int x = sx; x < ex; x++)
							    {
							        const u8 c = source[x_index >> 16];
							        if (c != 0xff)
							        {
							            if (pri[x] <= zpos)
							            {
							                switch(c)
							                {
							                case 0:
							                    dest[x] = 0x4000 | (dest[x] & 0x1fff);
							                    break;
							                case 1:
							                    dest[x] = 0x6000 | (dest[x] & 0x1fff);
							                    break;
							                default:
							                    dest[x] = pal[c];
							                    break;
							                }
							                pri[x] = zpos;
							            }
							        }
							        x_index += dx;
							    }
							    y_index += dy;
							}
							else
							*/
							{
								for (int x = sx; x < ex; x++)
								{
									const u8 c = source[x_index >> 16];
									if (c != 0xff)
									{
										if (pri[x] <= zpos)
										{
											if (color == 0xf && c==0xfe && shadow_offset)
											{
												dest[x] |= shadow_offset;
											}
											else
											{
												dest[x] = pal[c];
											}
											pri[x] = zpos;
										}
									}
									x_index += dx;
								}
								y_index += dy;
							}
						}
					}
				}
			}
		}
	}
} /* zdrawgfxzoom */

void namcos2_sprite_device::zdrawgfxzoom(
		screen_device &screen,
		bitmap_rgb32 &dest_bmp,const rectangle &clip,gfx_element *gfx,
		u32 code,u32 color,bool flipx,bool flipy,int sx,int sy,
		int scalex, int scaley, int zpos)
{
	/* nop */
}

void namcos2_sprite_device::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int pri, int control)
{
	int offset = (control & 0x000f) * (128 * 4);
	if (pri == 0)
	{
		screen.priority().fill(0, cliprect);
	}
	for (int loop = 0; loop < 128; loop++)
	{
		/****************************************
		* word#0
		*   Sprite Y position           D00-D08
		*   Sprite Size 16/32           D09
		*   Sprite Size Y               D10-D15
		*
		* word#1
		*   Sprite Quadrant             D00-D01
		*   Sprite Number               D02-D13
		*   Sprite flip X               D14
		*   Sprite flip Y               D15
		*
		* word#2
		*   Sprite X position           D00-D10
		*
		* word#3
		*   Sprite priority             D00-D02
		*   Sprite colour index         D04-D07
		*   Sprite Size X               D10-D15
		*/
		const u16 word3 = m_spriteram[offset + (loop * 4) + 3];
		if ((word3 & 0xf) == pri)
		{
			const u16 word0   = m_spriteram[offset + (loop * 4) + 0];
			const u16 word1   = m_spriteram[offset + (loop * 4) + 1];
			const u16 offset4 = m_spriteram[offset + (loop * 4) + 2];

			const int sizey = ((word0 >> 10) & 0x003f) + 1;
			int sizex       =  (word3 >> 10) & 0x003f;

			if ((word0 & 0x0200) == 0) sizex >>= 1;

			if ((sizey - 1) && sizex)
			{
				const u32 color  = (word3 >> 4) & 0x000f;
				const u32 sprn   = (word1 >> 2) & 0x0fff;
				const int ypos   = (0x1ff - (word0 & 0x01ff)) - 0x50 + 0x02;
				const int xpos   = (offset4 & 0x03ff) - 0x50 + 0x07;
				const bool flipy = word1 & 0x8000;
				const bool flipx = word1 & 0x4000;
				const int scalex = (sizex << 16) / ((word0 & 0x0200) ? 0x20 : 0x10);
				const int scaley = (sizey << 16) / ((word0 & 0x0200) ? 0x20 : 0x10);
				if (scalex && scaley)
				{
					gfx_element *gfx = m_gfxdecode->gfx(0);

					if ((word0 & 0x0200) == 0)
						gfx->set_source_clip((word1 & 0x0001) ? 16 : 0, 16, (word1 & 0x0002) ? 16 : 0, 16);
					else
						gfx->set_source_clip(0, 32, 0, 32);

					zdrawgfxzoom(
						screen,
						bitmap,
						cliprect,
						gfx,
						sprn,
						color,
						flipx,flipy,
						xpos,ypos,
						scalex,scaley,
						loop);
				}
			}
		}
	}
} /* draw_sprites */

void namcos2_sprite_device::draw_sprites_metalhawk(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int pri)
{
	/**
	 * word#0
	 *  xxxxxx---------- ysize
	 *  ------x--------- sprite tile size
	 *  -------xxxxxxxxx screeny
	 *
	 * word#1
	 *  --xxxxxxxxxxxxxx tile
	 *
	 * word#2 (unused)
	 *
	 * word#3
	 *  xxxxxx---------- xsize
	 *  ------xxxxxxxxxx screenx
	 *
	 * word#4 (unused)
	 * word#5 (unused)
	 *
	 * word#6 (orientation)
	 *  ---------------x rot90
	 *  --------------x- flipx
	 *  -------------x-- flipy
	 *  ------------x--- tile size
	 *
	 * word#7
	 *  ------------xxxx priority
	 *  --------xxxx---- color
	 *  x--------------- unknown
	 */
	const u16 *pSource = m_spriteram;
	if (pri == 0)
	{
		screen.priority().fill(0, cliprect);
	}
	for (int loop=0; loop < 128; loop++)
	{
		const u16 ypos  = pSource[0];
		const u16 tile  = pSource[1];
		const u16 xpos  = pSource[3];
		const u16 flags = pSource[6];
		const u16 attrs = pSource[7];
		const int sizey = ((ypos >> 10) & 0x003f) + 1;
		const int sizex =  (xpos >> 10) & 0x003f;
		const u32 sprn  =  (tile >>  2) & 0x0fff;

		if ((sizey - 1) && sizex && (attrs & 0xf) == pri)
		{
			const bool bBigSprite = flags & 0x0008;
			const u32 color  = (attrs >> 4) & 0x000f;
			int sx           = (xpos & 0x03ff) - 0x50 + 0x07;
			int sy           = (0x1ff - (ypos & 0x01ff)) - 0x50 + 0x02;
			const bool flipx = flags & 0x0002;
			const bool flipy = flags & 0x0004;
			const int scalex = (sizex << 16) / (0x20);//(sizex << 16) / (bBigSprite ? 0x20 : 0x10); correct formula?
			const int scaley = (sizey << 16) / (bBigSprite ? 0x20 : 0x10);

			/* swap xy */
			const int rgn = (flags & 0x0001);

			gfx_element *gfx = m_gfxdecode->gfx(rgn);

			if (bBigSprite)
			{
				if (sizex < 0x20)
				{
					sx -= (0x20 - sizex) / 0x8;
				}
				if (sizey < 0x20)
				{
					sy += (0x20 - sizey) / 0xC;
				}
				gfx->set_source_clip(0, 32, 0, 32);
			}
			else
				gfx->set_source_clip((tile & 0x0001) ? 16 : 0, 16, (tile & 0x0002) ? 16 : 0, 16);

			zdrawgfxzoom(
				screen,
				bitmap,
				cliprect,
				gfx,
				sprn, color,
				flipx,flipy,
				sx,sy,
				scalex, scaley,
				loop);
		}
		pSource += 8;
	}
} /* draw_sprites_metalhawk */