1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria, David Haywood
3 // Video System Sprites (type 2)
4 // todo:
5 //  move various vsystem sprite functions here
6 //  unify common ones + convert to device
7 
8 //  this is probably the VS 8904/8905 combo
9 
10 // Spinal Breakers
11 // Power Spikes
12 // Karate Blazers
13 // Turbo Force
14 // Aero Fighters (older hardware types)
15 // World Beach Championships 97 (modern Power Spikes bootleg, not original hw)
16 // Welltris
17 // Formula 1 Grand Prix (1)
18 // Pipe Dream
19 
20 // there were lots of comments saying drivers using the
21 //  static const uint8_t zoomtable[16] = { 0,7,14,20,25,30,34,38,42,46,49,52,54,57,59,61 };
22 // table for zooming needed upgrading, are we sure this isn't one of the
23 // differences between this sprite chip and the one in vsystem_spr.c, pspikes zooming is very rough
24 
25 
26 #include "emu.h"
27 #include "vsystem_spr2.h"
28 
29 
30 DEFINE_DEVICE_TYPE(VSYSTEM_SPR2, vsystem_spr2_device, "vsystem2_spr", "Video System VS8904/VS8905 Sprites")
31 
vsystem_spr2_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)32 vsystem_spr2_device::vsystem_spr2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
33 	: device_t(mconfig, VSYSTEM_SPR2, tag, owner, clock)
34 	, m_newtilecb(*this, DEVICE_SELF, FUNC(vsystem_spr2_device::tile_callback_noindirect))
35 	, m_pritype(0) // hack until we have better handling
36 	, m_gfx_region(0)
37 	, m_xoffs(0)
38 	, m_yoffs(0)
39 	, m_curr_sprite()
40 	, m_gfxdecode(*this, finder_base::DUMMY_TAG)
41 {
42 }
43 
tile_callback_noindirect(uint32_t tile)44 uint32_t vsystem_spr2_device::tile_callback_noindirect(uint32_t tile)
45 {
46 	return tile;
47 }
48 
49 
device_start()50 void vsystem_spr2_device::device_start()
51 {
52 	// bind our handler
53 	m_newtilecb.resolve();
54 }
55 
device_reset()56 void vsystem_spr2_device::device_reset()
57 {
58 }
59 
60 
get(uint16_t const * ram)61 bool vsystem_spr2_device::sprite_attributes::get(uint16_t const *ram)
62 {
63 	// sprite is disabled
64 	if (!(ram[2] & 0x0080))
65 		return false;
66 
67 	oy    =  (ram[0] & 0x01ff);
68 	zoomy =  (ram[0] & 0xf000) >> 12;
69 
70 	ox =     (ram[1] & 0x01ff);
71 	zoomx =  (ram[1] & 0xf000) >> 12;
72 
73 	xsize =  (ram[2] & 0x0700) >> 8;
74 	flipx =  (ram[2] & 0x0800);
75 
76 	ysize =  (ram[2] & 0x7000) >> 12;
77 	flipy =  (ram[2] & 0x8000);
78 
79 	color =  (ram[2] & 0x000f);
80 	pri =    (ram[2] & 0x0010);
81 
82 	map =    (ram[3]);
83 
84 	return true;
85 }
86 
handle_xsize_map_inc()87 void vsystem_spr2_device::sprite_attributes::handle_xsize_map_inc()
88 {
89 	if (xsize == 2) map += 1;
90 	if (xsize == 4) map += 3;
91 	if (xsize == 5) map += 2;
92 	if (xsize == 6) map += 1;
93 }
94 
95 template<class BitmapClass>
turbofrc_draw_sprites_common(uint16_t const * spriteram3,int spriteram3_bytes,int spritepalettebank,BitmapClass & bitmap,const rectangle & cliprect,bitmap_ind8 & priority_bitmap,int pri_param,bool flip_screen)96 void vsystem_spr2_device::turbofrc_draw_sprites_common(uint16_t const *spriteram3,  int spriteram3_bytes, int spritepalettebank, BitmapClass &bitmap, const rectangle &cliprect, bitmap_ind8 &priority_bitmap, int pri_param, bool flip_screen)
97 {
98 	int attr_start, first;
99 	first = 4 * spriteram3[0x1fe];
100 
101 	first &= 0x1ff;
102 	if (first>0x200-4)
103 		first = 0x200-4;
104 
105 	int start,end,inc;
106 
107 	if (m_pritype == 0 || m_pritype == 1 || m_pritype == 2) // prdrawgfx cases
108 	{
109 		start = 0x200 - 8;
110 		end = first-4;
111 		inc = -4;
112 	}
113 	else // drawgfx cases
114 	{
115 		start = first;
116 		end = 0x200 -4;
117 		inc = 4;
118 	}
119 
120 	for (attr_start = start; attr_start != end; attr_start += inc)
121 	{
122 		int x, y;
123 
124 		if (!m_curr_sprite.get(&spriteram3[attr_start]))
125 			continue;
126 
127 		// pipedrm
128 		m_curr_sprite.ox  += m_xoffs;
129 		m_curr_sprite.oy  += m_yoffs;
130 
131 		int usepri = 0;
132 
133 		// these are still calling the function multiple times to filter out priorities, even if some are also using pdrawgfx(!)
134 		if (m_pritype == 0 || m_pritype == 1 || m_pritype == 3) // turbo force, spinlbrk, pipedrm etc.
135 		{
136 			if ((m_curr_sprite.pri>>4) != pri_param)
137 				continue;
138 		}
139 
140 
141 		if (m_pritype == 0) // turbo force etc.
142 		{
143 			usepri = m_curr_sprite.pri ? 0 : 2;
144 		}
145 		else if (m_pritype == 1) // spinlbrk
146 		{
147 			usepri = m_curr_sprite.pri ? 2 : 0;
148 		}
149 		else if (m_pritype == 2) // f1gp
150 		{
151 			usepri = pri_param;
152 		}
153 
154 		bool fx = m_curr_sprite.flipx != 0;
155 		bool fy = m_curr_sprite.flipy != 0;
156 		if (flip_screen)
157 		{
158 			m_curr_sprite.ox = 308 - m_curr_sprite.ox;
159 			m_curr_sprite.oy = 208 - m_curr_sprite.oy;
160 			fx = !fx;
161 			fy = !fy;
162 		}
163 
164 		m_curr_sprite.color += 16 * spritepalettebank;
165 
166 		m_curr_sprite.zoomx = 32 - m_curr_sprite.zoomx;
167 		m_curr_sprite.zoomy = 32 - m_curr_sprite.zoomy;
168 
169 		for (y = 0; y <= m_curr_sprite.ysize; y++)
170 		{
171 			int cy = m_curr_sprite.flipy ? (m_curr_sprite.ysize - y) : y;
172 			int sy = ((m_curr_sprite.oy + m_curr_sprite.zoomy * (flip_screen ? -cy : cy) / 2 + 16) & 0x1ff) - 16;
173 
174 			for (x = 0; x <= m_curr_sprite.xsize; x++)
175 			{
176 				int cx = m_curr_sprite.flipx ? (m_curr_sprite.xsize - x) : x;
177 				int sx = ((m_curr_sprite.ox + m_curr_sprite.zoomx * (flip_screen ? -cx : cx) / 2 + 16) & 0x1ff) - 16;
178 
179 				int curr = m_newtilecb(m_curr_sprite.map++);
180 
181 				if (m_pritype == 0 || m_pritype == 1 || m_pritype == 2) // pdrawgfx cases
182 				{
183 					m_gfxdecode->gfx(m_gfx_region)->prio_zoom_transpen(bitmap,cliprect, curr, m_curr_sprite.color, fx, fy, sx-0x000,sy-0x000, m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11,  priority_bitmap,usepri,15);
184 					m_gfxdecode->gfx(m_gfx_region)->prio_zoom_transpen(bitmap,cliprect, curr, m_curr_sprite.color, fx, fy, sx-0x200,sy-0x000, m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11,  priority_bitmap,usepri,15);
185 					m_gfxdecode->gfx(m_gfx_region)->prio_zoom_transpen(bitmap,cliprect, curr, m_curr_sprite.color, fx, fy, sx-0x000,sy-0x200, m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11,  priority_bitmap,usepri,15);
186 					m_gfxdecode->gfx(m_gfx_region)->prio_zoom_transpen(bitmap,cliprect, curr, m_curr_sprite.color, fx, fy, sx-0x200,sy-0x200, m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11,  priority_bitmap,usepri,15);
187 				}
188 				else // drawgfx cases (welltris, pipedrm)
189 				{
190 					m_gfxdecode->gfx(m_gfx_region)->zoom_transpen(bitmap,cliprect, curr, m_curr_sprite.color, fx, fy, sx-0x000,sy-0x000, m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11,15);
191 					m_gfxdecode->gfx(m_gfx_region)->zoom_transpen(bitmap,cliprect, curr, m_curr_sprite.color, fx, fy, sx-0x200,sy-0x000, m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11,15);
192 					m_gfxdecode->gfx(m_gfx_region)->zoom_transpen(bitmap,cliprect, curr, m_curr_sprite.color, fx, fy, sx-0x000,sy-0x200, m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11,15);
193 					m_gfxdecode->gfx(m_gfx_region)->zoom_transpen(bitmap,cliprect, curr, m_curr_sprite.color, fx, fy, sx-0x200,sy-0x200, m_curr_sprite.zoomx << 11, m_curr_sprite.zoomy << 11,15);
194 				}
195 
196 			}
197 			m_curr_sprite.handle_xsize_map_inc();
198 		}
199 	}
200 }
201 
turbofrc_draw_sprites(uint16_t const * spriteram3,int spriteram3_bytes,int spritepalettebank,bitmap_ind16 & bitmap,const rectangle & cliprect,bitmap_ind8 & priority_bitmap,int pri_param,bool flip_screen)202 void vsystem_spr2_device::turbofrc_draw_sprites(uint16_t const *spriteram3,  int spriteram3_bytes, int spritepalettebank, bitmap_ind16 &bitmap, const rectangle &cliprect, bitmap_ind8 &priority_bitmap, int pri_param, bool flip_screen)
203 {
204 	turbofrc_draw_sprites_common(spriteram3, spriteram3_bytes, spritepalettebank, bitmap, cliprect, priority_bitmap, pri_param, flip_screen);
205 }
206 
turbofrc_draw_sprites(uint16_t const * spriteram3,int spriteram3_bytes,int spritepalettebank,bitmap_rgb32 & bitmap,const rectangle & cliprect,bitmap_ind8 & priority_bitmap,int pri_param,bool flip_screen)207 void vsystem_spr2_device::turbofrc_draw_sprites(uint16_t const *spriteram3,  int spriteram3_bytes, int spritepalettebank, bitmap_rgb32 &bitmap, const rectangle &cliprect, bitmap_ind8 &priority_bitmap, int pri_param, bool flip_screen)
208 {
209 	turbofrc_draw_sprites_common(spriteram3, spriteram3_bytes, spritepalettebank, bitmap, cliprect, priority_bitmap, pri_param, flip_screen);
210 }
211