summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/video/vsystem_spr.cpp
blob: b0a2e11eba6b87ac53fbcacb2e982778503679a0 (plain) (tree)
1
2
3
4
5
6
7
8

                                                   

                       
                                                                                                      

                                                              
 










                                  









































                                                                                                      
                
                        
                   
 
 
                                                                                                 
 
                                                                                                                       









                                                                               
                                                    
 

 
                                                                    

                    

 



                                               
 
                                    
 










                                             



                                       

 
                                                                    
 
          



















                                                            
 


                                        
 


                                        
 




                                        
 
                                  
 
 
 
                                                                                                                             
 
                                                          
                                 
 

                                    
 
                    
         
                                          
                 
                                



                                                            
                 

         

                                                       

                               
 

                                                                                         





                                       

                                                                                                 



                                    
                                                                       

                                    



                                                                                                                                                                                                                                                                                                                                                                                


                            



                                                                                                                                                                                                                                                                                                                                           
                         



                                   
 


 
 
                                                                                                                                                                                                 



                    
                                   
                                                              
         
                                                    


                   


                                                                                   
         


                                
         
            
         


                           
         
 


                            
         
                                                         
                 
                                       
 
                                                                    
 
                                                                  
 
                                                          
 


                                                                                                                                                              
                                                                                      
                                                                                                   


                            
                                                                                           
                         
                 

                          

         
// license:BSD-3-Clause
// copyright-holders:Nicola Salmoria, David Haywood
// Video System Sprites
// todo:
//  update drivers which call multiple priority passes to use the pdrawgfx version (aerofgt, gstriker)

//  according to gstriker this is probably the Fujitsu CG10103

// Aero Fighters (newer hardware)
// Quiz & Variety Sukusuku Inufuku
// 3 On 3 Dunk Madness
// Super Slams
// Formula 1 Grand Prix 2
// (Lethal) Crash Race
// Grand Striker
// V Goal Soccer
// Tecmo World Cup '94
// Tao Taido

/* old notes */

/*** Fujitsu CG10103 **********************************************/

/*
    Fujitsu CG10103 sprite generator
    --------------------------------

- Tile based
- 16x16 4bpp tiles
- Up to 7x7 in each block
- 5 bit of palette selection for the mixer
- Scaling (x/y)
- Flipping
- Indipendent sorting list
- 1 bit of pri for the mixer

Note that this chip can be connected to a VS9210 which adds a level of indirection for
tile numbers. Basically, the VS9210 indirects the tilet number through a table in its attached
memory, before accessing the ROMs.


    Sorting list format (VideoRAM offset 0)
    ---------------------------------------

de-- ---f ssss ssss

e=end of list
f=sprite present in this position
s=sprite index
d=disable sprite?


TODO:
Priorities should be right, but they probably need to be orthogonal with the mixer priorities.
Zoom factor is not correct, the scale is probably non-linear
Horizontal wrapping is just a hack. The chip probably calculates if it needs to draw the sprite at the
  normal position, or wrapped along X/Y.
Abstracts the VS9210

*/

#include "emu.h"
#include "vsystem_spr.h"
#include "screen.h"


DEFINE_DEVICE_TYPE(VSYSTEM_SPR, vsystem_spr_device, "vsystem_spr", "Video System VS9108 Sprites")

vsystem_spr_device::vsystem_spr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, VSYSTEM_SPR, tag, owner, clock)
	, m_newtilecb(FUNC(vsystem_spr_device::tile_callback_noindirect), this)
	, m_xoffs(0)
	, m_yoffs(0)
	, m_pdraw(false)
	, m_pal_mask(0x3f)
	, m_gfx_region(-1)
	, m_transpen(15)
	, m_pal_base(0)
	, m_curr_sprite()
	, m_gfxdecode(*this, finder_base::DUMMY_TAG)
{
}

uint32_t vsystem_spr_device::tile_callback_noindirect(uint32_t tile)
{
	return tile;
}

void vsystem_spr_device::device_start()
{
	// bind our handler
	m_newtilecb.bind_relative_to(*owner());

	save_item(NAME(m_pal_base));

	save_item(NAME(m_curr_sprite.ox));
	save_item(NAME(m_curr_sprite.xsize));
	save_item(NAME(m_curr_sprite.zoomx));
	save_item(NAME(m_curr_sprite.oy));
	save_item(NAME(m_curr_sprite.ysize));
	save_item(NAME(m_curr_sprite.zoomy));
	save_item(NAME(m_curr_sprite.flipx));
	save_item(NAME(m_curr_sprite.flipy));
	save_item(NAME(m_curr_sprite.color));
	save_item(NAME(m_curr_sprite.pri));
	save_item(NAME(m_curr_sprite.map));
}

void vsystem_spr_device::device_reset()
{
}

void vsystem_spr_device::sprite_attributes::get(uint16_t const *ram)
{
	/*
	    attr_start + 0x0000
	    ---- ---x xxxx xxxx oy
	    ---- xxx- ---- ---- ysize
	    xxxx ---- ---- ---- zoomy

	    attr_start + 0x0001
	    ---- ---x xxxx xxxx ox
	    ---- xxx- ---- ---- xsize
	    xxxx ---- ---- ---- zoomx

	    attr_start + 0x0002
	    -x-- ---- ---- ---- flipx
	    x--- ---- ---- ---- flipy
	    --xx xxxx ---- ---- color
	    --xx ---- ---- ---- priority? (upper color bits)
	    ---- ---- ---- ---x map start (msb)

	    attr_start + 0x0003
	    xxxx xxxx xxxx xxxx map start (lsb)
	*/

	oy =    (ram[0] & 0x01ff);
	ysize = (ram[0] & 0x0e00) >> 9;
	zoomy = (ram[0] & 0xf000) >> 12;

	ox =    (ram[1] & 0x01ff);
	xsize = (ram[1] & 0x0e00) >> 9;
	zoomx = (ram[1] & 0xf000) >> 12;

	flipx = (ram[2] & 0x4000);
	flipy = (ram[2] & 0x8000);
	color = (ram[2] & 0x3f00) >> 8;
	pri   = (ram[2] & 0x3000) >> 12;
	map   = (ram[2] & 0x0001) << 16;

	map  |= (ram[3] & 0xffff);
}


void vsystem_spr_device::common_sprite_drawgfx(bitmap_ind16 &bitmap, const rectangle &cliprect, bitmap_ind8 &priority_bitmap)
{
	gfx_element *gfx = m_gfxdecode->gfx(m_gfx_region);
	int priority_mask = 0x00;

	m_curr_sprite.oy += m_yoffs;
	m_curr_sprite.ox += m_xoffs;

	if (m_pdraw)
	{
		switch (m_curr_sprite.pri)
		{
			default:
			case 0: priority_mask = 0x00; break;
			case 3: priority_mask = 0xfe; break;
			case 2: priority_mask = 0xfc; break;
			case 1: priority_mask = 0xf0; break;
		}
	}

	m_curr_sprite.zoomx = 32 - m_curr_sprite.zoomx;
	m_curr_sprite.zoomy = 32 - m_curr_sprite.zoomy;

	int ystart, yend, yinc;

	if (!m_curr_sprite.flipy) { ystart = 0; yend = m_curr_sprite.ysize+1; yinc = 1; }
	else                    { ystart = m_curr_sprite.ysize; yend = -1; yinc = -1; }

	int ycnt = ystart;
	while (ycnt != yend)
	{
		int xstart, xend, xinc;

		if (!m_curr_sprite.flipx) { xstart = 0; xend = m_curr_sprite.xsize+1; xinc = 1; }
		else                    { xstart = m_curr_sprite.xsize; xend = -1; xinc = -1; }

		int xcnt = xstart;
		while (xcnt != xend)
		{
			int startno = m_newtilecb(m_curr_sprite.map++);
			if (m_pdraw)
			{
				gfx->prio_zoom_transpen(bitmap,cliprect, startno, m_curr_sprite.color + m_pal_base, m_curr_sprite.flipx, m_curr_sprite.flipy, m_curr_sprite.ox + xcnt * m_curr_sprite.zoomx/2,        m_curr_sprite.oy + ycnt * m_curr_sprite.zoomy/2,        m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11, priority_bitmap, priority_mask, m_transpen);
				gfx->prio_zoom_transpen(bitmap,cliprect, startno, m_curr_sprite.color + m_pal_base, m_curr_sprite.flipx, m_curr_sprite.flipy, -0x200+m_curr_sprite.ox + xcnt * m_curr_sprite.zoomx/2, m_curr_sprite.oy + ycnt * m_curr_sprite.zoomy/2,        m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11, priority_bitmap, priority_mask, m_transpen);
				gfx->prio_zoom_transpen(bitmap,cliprect, startno, m_curr_sprite.color + m_pal_base, m_curr_sprite.flipx, m_curr_sprite.flipy, m_curr_sprite.ox + xcnt * m_curr_sprite.zoomx/2,        -0x200+m_curr_sprite.oy + ycnt * m_curr_sprite.zoomy/2, m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11, priority_bitmap, priority_mask, m_transpen);
				gfx->prio_zoom_transpen(bitmap,cliprect, startno, m_curr_sprite.color + m_pal_base, m_curr_sprite.flipx, m_curr_sprite.flipy, -0x200+m_curr_sprite.ox + xcnt * m_curr_sprite.zoomx/2, -0x200+m_curr_sprite.oy + ycnt * m_curr_sprite.zoomy/2, m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11, priority_bitmap, priority_mask, m_transpen);
			}
			else
			{
				gfx->zoom_transpen(bitmap,cliprect, startno, m_curr_sprite.color + m_pal_base, m_curr_sprite.flipx, m_curr_sprite.flipy, m_curr_sprite.ox + xcnt * m_curr_sprite.zoomx/2,        m_curr_sprite.oy + ycnt * m_curr_sprite.zoomy/2,        m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11, m_transpen);
				gfx->zoom_transpen(bitmap,cliprect, startno, m_curr_sprite.color + m_pal_base, m_curr_sprite.flipx, m_curr_sprite.flipy, -0x200+m_curr_sprite.ox + xcnt * m_curr_sprite.zoomx/2, m_curr_sprite.oy + ycnt * m_curr_sprite.zoomy/2,        m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11, m_transpen);
				gfx->zoom_transpen(bitmap,cliprect, startno, m_curr_sprite.color + m_pal_base, m_curr_sprite.flipx, m_curr_sprite.flipy, m_curr_sprite.ox + xcnt * m_curr_sprite.zoomx/2,        -0x200+m_curr_sprite.oy + ycnt * m_curr_sprite.zoomy/2, m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11, m_transpen);
				gfx->zoom_transpen(bitmap,cliprect, startno, m_curr_sprite.color + m_pal_base, m_curr_sprite.flipx, m_curr_sprite.flipy, -0x200+m_curr_sprite.ox + xcnt * m_curr_sprite.zoomx/2, -0x200+m_curr_sprite.oy + ycnt * m_curr_sprite.zoomy/2, m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11, m_transpen);
			}
			xcnt+=xinc;
		}
		ycnt+=yinc;
	}

}



void vsystem_spr_device::draw_sprites(uint16_t const *spriteram, int spriteram_bytes, screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int prihack_mask, int prihack_val )
{
	int offs;
	int end = 0;

	// find the end of the list
	for (offs = 0; offs < (spriteram_bytes / 16 ); offs++)
	{
		if (spriteram[offs] & 0x4000) break;
	}
	end = offs;

	// decide our drawing order (if we're using pdrawgfx we must go in reverse)
	int first, last, inc;
	if (m_pdraw)
	{
		first = end - 1;
		last = -1;
		inc = -1;
	}
	else
	{
		first = 0;
		last = end;
		inc = 1;
	}

	// draw
	offs = first;
	while (offs != last)
	{
		if ((spriteram[offs] & 0x8000) == 0x0000)
		{
			int attr_start;

			attr_start = 4 * (spriteram[offs] & 0x03ff);

			m_curr_sprite.get(&spriteram[attr_start]);

			m_curr_sprite.color &= m_pal_mask;

			// hack for aero fighters and other which still call us multiple times with different priorities instead of using the pdrawgfx version
			if (prihack_mask != -1)
			{
				if ((m_curr_sprite.pri & prihack_mask) == prihack_val)
					common_sprite_drawgfx(bitmap, cliprect, screen.priority());
			}
			else
			{
				common_sprite_drawgfx(bitmap, cliprect, screen.priority());
			}
		}

		offs+=inc;
	}
}