1 // license:BSD-3-Clause
2 // copyright-holders:Ernesto Corvi,Tim Lindquist,Carlos A. Lozano,Bryan McPhail,Jarek Parchanski,Nicola Salmoria,Tomasz Slanina,Phil Stroffolino,Acho A. Tang,Victor Trucco
3 // thanks-to:Marco Cassili
4 #include "emu.h"
5 #include "includes/snk.h"
6 
7 /*******************************************************************************
8  Shadow Handling Notes
9 ********************************************************************************
10  Shadows are handled by changing palette bank.
11 
12  Games Not Using Shadows
13 
14  those using gwar_vh_screenrefresh (gwar, bermudat, psychos, chopper1)
15     (0-15 , 15 is transparent)
16 
17  Games Using Shadows
18 
19  those using tnk3_vh_screenrefresh (tnk3, athena, fitegolf) sgladiat is similar
20     (0-7  , 6  is shadow, 7  is transparent) * these are using aso colour prom convert *
21  those using ikari_vh_screenrefresh (ikari, victroad)
22     (0-7  , 6  is shadow, 7  is transparent)
23  those using tdfever_vh_screenrefresh (tdfever, fsoccer)
24     (0-15 , 14 is shadow, 15 is transparent)
25 
26 *******************************************************************************/
27 
28 
29 /**************************************************************************************/
30 
tnk3_palette(palette_device & palette) const31 void snk_state::tnk3_palette(palette_device &palette) const
32 {
33 	uint8_t const *const color_prom = memregion("proms")->base();
34 	constexpr int num_colors = 0x400;
35 
36 	for (int i = 0; i < num_colors; i++)
37 	{
38 		int bit0, bit1, bit2, bit3;
39 
40 		bit0 = BIT(color_prom[i + 2*num_colors], 3);
41 		bit1 = BIT(color_prom[i], 1);
42 		bit2 = BIT(color_prom[i], 2);
43 		bit3 = BIT(color_prom[i], 3);
44 		int const r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
45 
46 		bit0 = BIT(color_prom[i + 2*num_colors], 2);
47 		bit1 = BIT(color_prom[i + num_colors], 2);
48 		bit2 = BIT(color_prom[i + num_colors], 3);
49 		bit3 = BIT(color_prom[i], 0);
50 		int const g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
51 
52 		bit0 = BIT(color_prom[i + 2*num_colors], 0);
53 		bit1 = BIT(color_prom[i + 2*num_colors], 1);
54 		bit2 = BIT(color_prom[i + num_colors], 0);
55 		bit3 = BIT(color_prom[i + num_colors], 1);
56 		int const b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
57 
58 		palette.set_pen_color(i, rgb_t(r, g, b));
59 	}
60 }
61 
62 /**************************************************************************************/
63 
TILEMAP_MAPPER_MEMBER(snk_state::marvins_tx_scan_cols)64 TILEMAP_MAPPER_MEMBER(snk_state::marvins_tx_scan_cols)
65 {
66 	// tilemap is 36x28, the central part is from the first RAM page and the
67 	// extra 4 columns are from the second page
68 	col -= 2;
69 	if (col & 0x20)
70 		return 0x400 + row + ((col & 0x1f) << 5);
71 	else
72 		return row + (col << 5);
73 }
74 
TILE_GET_INFO_MEMBER(snk_state::marvins_get_tx_tile_info)75 TILE_GET_INFO_MEMBER(snk_state::marvins_get_tx_tile_info)
76 {
77 	int code = m_tx_videoram[tile_index];
78 	int color = code >> 5;
79 
80 	tileinfo.set(0,
81 			m_tx_tile_offset + code,
82 			color,
83 			tile_index & 0x400 ? TILE_FORCE_LAYER0 : 0);
84 }
85 
TILE_GET_INFO_MEMBER(snk_state::ikari_get_tx_tile_info)86 TILE_GET_INFO_MEMBER(snk_state::ikari_get_tx_tile_info)
87 {
88 	int code = m_tx_videoram[tile_index];
89 
90 	tileinfo.set(0,
91 			m_tx_tile_offset + code,
92 			0,
93 			tile_index & 0x400 ? TILE_FORCE_LAYER0 : 0);
94 }
95 
TILE_GET_INFO_MEMBER(snk_state::gwar_get_tx_tile_info)96 TILE_GET_INFO_MEMBER(snk_state::gwar_get_tx_tile_info)
97 {
98 	int code = m_tx_videoram[tile_index];
99 
100 	tileinfo.set(0,
101 			m_tx_tile_offset + code,
102 			0,
103 			0);
104 }
105 
106 
TILE_GET_INFO_MEMBER(snk_state::marvins_get_fg_tile_info)107 TILE_GET_INFO_MEMBER(snk_state::marvins_get_fg_tile_info)
108 {
109 	int code = m_fg_videoram[tile_index];
110 
111 	tileinfo.set(1,
112 			code,
113 			0,
114 			0);
115 }
116 
TILE_GET_INFO_MEMBER(snk_state::marvins_get_bg_tile_info)117 TILE_GET_INFO_MEMBER(snk_state::marvins_get_bg_tile_info)
118 {
119 	int code = m_bg_videoram[tile_index];
120 
121 	tileinfo.set(2,
122 			code,
123 			0,
124 			0);
125 }
126 
127 
TILE_GET_INFO_MEMBER(snk_state::aso_get_bg_tile_info)128 TILE_GET_INFO_MEMBER(snk_state::aso_get_bg_tile_info)
129 {
130 	int code = m_bg_videoram[tile_index];
131 
132 	tileinfo.set(1,
133 			m_bg_tile_offset + code,
134 			0,
135 			0);
136 }
137 
TILE_GET_INFO_MEMBER(snk_state::tnk3_get_bg_tile_info)138 TILE_GET_INFO_MEMBER(snk_state::tnk3_get_bg_tile_info)
139 {
140 	int attr = m_bg_videoram[2*tile_index+1];
141 	int code = m_bg_videoram[2*tile_index] | ((attr & 0x30) << 4);
142 	int color = (attr & 0xf) ^ 8;
143 
144 	tileinfo.set(1,
145 			code,
146 			color,
147 			0);
148 }
149 
TILE_GET_INFO_MEMBER(snk_state::ikari_get_bg_tile_info)150 TILE_GET_INFO_MEMBER(snk_state::ikari_get_bg_tile_info)
151 {
152 	int attr = m_bg_videoram[2*tile_index+1];
153 	int code = m_bg_videoram[2*tile_index] | ((attr & 0x03) << 8);
154 	int color = (attr & 0x70) >> 4;
155 
156 	tileinfo.set(1,
157 			code,
158 			color,
159 			0);
160 }
161 
TILE_GET_INFO_MEMBER(snk_state::gwar_get_bg_tile_info)162 TILE_GET_INFO_MEMBER(snk_state::gwar_get_bg_tile_info)
163 {
164 	int attr = m_bg_videoram[2*tile_index+1];
165 	int code = m_bg_videoram[2*tile_index] | ((attr & 0x0f) << 8);
166 	int color = (attr & 0xf0) >> 4;
167 
168 	if (m_is_psychos)   // psychos has a separate palette bank bit
169 		color &= 7;
170 
171 	tileinfo.set(1,
172 			code,
173 			color,
174 			0);
175 
176 	// bermudat, tdfever use FFFF to blank the background.
177 	// (still call tileinfo.set, otherwise problems might occur on boot when
178 	// the tile data hasn't been initialised)
179 	if (code >= m_gfxdecode->gfx(1)->elements())
180 		tileinfo.pen_data = m_empty_tile;
181 }
182 
183 
184 /**************************************************************************************/
185 
VIDEO_START_MEMBER(snk_state,snk_3bpp_shadow)186 VIDEO_START_MEMBER(snk_state,snk_3bpp_shadow)
187 {
188 	int i;
189 
190 	if(!(m_palette->shadows_enabled()))
191 		fatalerror("driver should use VIDEO_HAS_SHADOWS\n");
192 
193 	/* prepare shadow draw table */
194 	for(i = 0; i <= 5; i++) m_drawmode_table[i] = DRAWMODE_SOURCE;
195 	m_drawmode_table[6] = (m_palette->shadows_enabled()) ? DRAWMODE_SHADOW : DRAWMODE_SOURCE;
196 	m_drawmode_table[7] = DRAWMODE_NONE;
197 
198 	for (i = 0x000;i < 0x400;i++)
199 		m_palette->shadow_table()[i] = i | 0x200;
200 }
201 
VIDEO_START_MEMBER(snk_state,snk_4bpp_shadow)202 VIDEO_START_MEMBER(snk_state,snk_4bpp_shadow)
203 {
204 	int i;
205 
206 	if(!(m_palette->shadows_enabled()))
207 		fatalerror("driver should use VIDEO_HAS_SHADOWS\n");
208 
209 	/* prepare shadow draw table */
210 	for(i = 0; i <= 13; i++) m_drawmode_table[i] = DRAWMODE_SOURCE;
211 	m_drawmode_table[14] = DRAWMODE_SHADOW;
212 	m_drawmode_table[15] = DRAWMODE_NONE;
213 
214 	/* all palette entries are not affected by shadow sprites... */
215 	for (i = 0x000;i < 0x400;i++)
216 		m_palette->shadow_table()[i] = i;
217 	/* ... except for tilemap colors */
218 	for (i = 0x200;i < 0x300;i++)
219 		m_palette->shadow_table()[i] = i + 0x100;
220 }
221 
222 
VIDEO_START_MEMBER(snk_state,marvins)223 VIDEO_START_MEMBER(snk_state,marvins)
224 {
225 	VIDEO_START_CALL_MEMBER(snk_3bpp_shadow);
226 
227 	m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(snk_state::marvins_get_tx_tile_info)), tilemap_mapper_delegate(*this, FUNC(snk_state::marvins_tx_scan_cols)), 8, 8, 36, 28);
228 	m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(snk_state::marvins_get_fg_tile_info)), TILEMAP_SCAN_COLS, 8, 8, 64, 32);
229 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(snk_state::marvins_get_bg_tile_info)), TILEMAP_SCAN_COLS, 8, 8, 64, 32);
230 
231 	m_tx_tilemap->set_transparent_pen(15);
232 	m_tx_tilemap->set_scrolldy(8, 8);
233 
234 	m_fg_tilemap->set_transparent_pen(15);
235 	m_fg_tilemap->set_scrolldx(15,  31);
236 	m_fg_tilemap->set_scrolldy(8, -32);
237 
238 	m_bg_tilemap->set_scrolldx(15,  31);
239 	m_bg_tilemap->set_scrolldy(8, -32);
240 
241 	m_tx_tile_offset = 0;
242 }
243 
VIDEO_START_MEMBER(snk_state,jcross)244 VIDEO_START_MEMBER(snk_state,jcross)
245 {
246 	VIDEO_START_CALL_MEMBER(snk_3bpp_shadow);
247 
248 	m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(snk_state::marvins_get_tx_tile_info)), tilemap_mapper_delegate(*this, FUNC(snk_state::marvins_tx_scan_cols)), 8, 8, 36, 28);
249 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(snk_state::aso_get_bg_tile_info)),     TILEMAP_SCAN_COLS, 8, 8, 64, 64);
250 
251 	m_tx_tilemap->set_transparent_pen(15);
252 	m_tx_tilemap->set_scrolldy(8, 8);
253 
254 	m_bg_tilemap->set_scrolldx(15, 24);
255 	m_bg_tilemap->set_scrolldy(8, -32);
256 
257 	m_num_sprites = 25;
258 	m_yscroll_mask = 0x1ff;
259 	m_bg_tile_offset = 0;
260 	m_tx_tile_offset = 0;
261 }
262 
VIDEO_START_MEMBER(snk_state,sgladiat)263 VIDEO_START_MEMBER(snk_state,sgladiat)
264 {
265 	VIDEO_START_CALL_MEMBER(snk_3bpp_shadow);
266 
267 	m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(snk_state::marvins_get_tx_tile_info)), tilemap_mapper_delegate(*this, FUNC(snk_state::marvins_tx_scan_cols)), 8, 8, 36, 28);
268 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(snk_state::aso_get_bg_tile_info)),     TILEMAP_SCAN_COLS, 8, 8, 64, 32);
269 
270 	m_tx_tilemap->set_transparent_pen(15);
271 	m_tx_tilemap->set_scrolldy(8, 8);
272 
273 	m_bg_tilemap->set_scrolldx(15, 24);
274 	m_bg_tilemap->set_scrolldy(8, -32);
275 
276 	m_num_sprites = 25;
277 	m_yscroll_mask = 0x0ff;
278 	m_bg_tile_offset = 0;
279 	m_tx_tile_offset = 0;
280 }
281 
VIDEO_START_MEMBER(snk_state,hal21)282 VIDEO_START_MEMBER(snk_state,hal21)
283 {
284 	VIDEO_START_CALL_MEMBER(jcross);
285 
286 	m_bg_tilemap->set_scrolldy(8, -32+256);
287 
288 	m_num_sprites = 50;
289 	m_yscroll_mask = 0x1ff;
290 }
291 
VIDEO_START_MEMBER(snk_state,aso)292 VIDEO_START_MEMBER(snk_state,aso)
293 {
294 	VIDEO_START_CALL_MEMBER(jcross);
295 
296 	m_bg_tilemap->set_scrolldx(15+256, 24+256);
297 
298 	m_num_sprites = 50;
299 	m_yscroll_mask = 0x1ff;
300 }
301 
302 
VIDEO_START_MEMBER(snk_state,tnk3)303 VIDEO_START_MEMBER(snk_state,tnk3)
304 {
305 	VIDEO_START_CALL_MEMBER(snk_3bpp_shadow);
306 
307 	m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(snk_state::marvins_get_tx_tile_info)), tilemap_mapper_delegate(*this, FUNC(snk_state::marvins_tx_scan_cols)), 8, 8, 36, 28);
308 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(snk_state::tnk3_get_bg_tile_info)),    TILEMAP_SCAN_COLS, 8, 8, 64, 64);
309 
310 	m_tx_tilemap->set_transparent_pen(15);
311 	m_tx_tilemap->set_scrolldy(8, 8);
312 
313 	m_bg_tilemap->set_scrolldx(15, 24);
314 	m_bg_tilemap->set_scrolldy(8, -32);
315 
316 	m_num_sprites = 50;
317 	m_yscroll_mask = 0x1ff;
318 	m_tx_tile_offset = 0;
319 }
320 
VIDEO_START_MEMBER(snk_state,ikari)321 VIDEO_START_MEMBER(snk_state,ikari)
322 {
323 	VIDEO_START_CALL_MEMBER(snk_3bpp_shadow);
324 
325 	m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(snk_state::ikari_get_tx_tile_info)), tilemap_mapper_delegate(*this, FUNC(snk_state::marvins_tx_scan_cols)), 8, 8, 36, 28);
326 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(snk_state::ikari_get_bg_tile_info)), TILEMAP_SCAN_COLS, 16, 16, 32, 32);
327 
328 	m_tx_tilemap->set_transparent_pen(15);
329 	m_tx_tilemap->set_scrolldy(8, 8);
330 
331 	m_bg_tilemap->set_scrolldx(15, 24);
332 	m_bg_tilemap->set_scrolldy(8, -32);
333 
334 	m_tx_tile_offset = 0;
335 }
336 
VIDEO_START_MEMBER(snk_state,gwar)337 VIDEO_START_MEMBER(snk_state,gwar)
338 {
339 	int i;
340 
341 	/* prepare drawmode table */
342 	for(i = 0; i <= 14; i++) m_drawmode_table[i] = DRAWMODE_SOURCE;
343 	m_drawmode_table[15] = DRAWMODE_NONE;
344 
345 	memset(m_empty_tile, 0xf, sizeof(m_empty_tile));
346 
347 	m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(snk_state::gwar_get_tx_tile_info)), TILEMAP_SCAN_COLS,  8,  8, 50, 32);
348 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(snk_state::gwar_get_bg_tile_info)), TILEMAP_SCAN_COLS, 16, 16, 32, 32);
349 
350 	m_tx_tilemap->set_transparent_pen(15);
351 
352 	m_bg_tilemap->set_scrolldx(16, 143);
353 	m_bg_tilemap->set_scrolldy(0, -32);
354 
355 	m_tx_tile_offset = 0;
356 
357 	m_is_psychos = 0;
358 }
359 
VIDEO_START_MEMBER(snk_state,psychos)360 VIDEO_START_MEMBER(snk_state,psychos)
361 {
362 	VIDEO_START_CALL_MEMBER(gwar);
363 	m_is_psychos = 1;
364 }
365 
VIDEO_START_MEMBER(snk_state,tdfever)366 VIDEO_START_MEMBER(snk_state,tdfever)
367 {
368 	VIDEO_START_CALL_MEMBER(gwar);
369 	VIDEO_START_CALL_MEMBER(snk_4bpp_shadow);
370 }
371 
372 /**************************************************************************************/
373 
snk_tx_videoram_w(offs_t offset,uint8_t data)374 void snk_state::snk_tx_videoram_w(offs_t offset, uint8_t data)
375 {
376 	m_tx_videoram[offset] = data;
377 	m_tx_tilemap->mark_tile_dirty(offset);
378 }
379 
marvins_fg_videoram_w(offs_t offset,uint8_t data)380 void snk_state::marvins_fg_videoram_w(offs_t offset, uint8_t data)
381 {
382 	m_fg_videoram[offset] = data;
383 	m_fg_tilemap->mark_tile_dirty(offset);
384 }
385 
marvins_bg_videoram_w(offs_t offset,uint8_t data)386 void snk_state::marvins_bg_videoram_w(offs_t offset, uint8_t data)
387 {
388 	m_bg_videoram[offset] = data;
389 	m_bg_tilemap->mark_tile_dirty(offset);
390 }
391 
snk_bg_videoram_w(offs_t offset,uint8_t data)392 void snk_state::snk_bg_videoram_w(offs_t offset, uint8_t data)
393 {
394 	m_bg_videoram[offset] = data;
395 	m_bg_tilemap->mark_tile_dirty(offset >> 1);
396 }
397 
398 
snk_fg_scrollx_w(uint8_t data)399 void snk_state::snk_fg_scrollx_w(uint8_t data)
400 {
401 	m_fg_scrollx = (m_fg_scrollx & ~0xff) | data;
402 }
403 
snk_fg_scrolly_w(uint8_t data)404 void snk_state::snk_fg_scrolly_w(uint8_t data)
405 {
406 	m_fg_scrolly = (m_fg_scrolly & ~0xff) | data;
407 }
408 
snk_bg_scrollx_w(uint8_t data)409 void snk_state::snk_bg_scrollx_w(uint8_t data)
410 {
411 	m_bg_scrollx = (m_bg_scrollx & ~0xff) | data;
412 }
413 
snk_bg_scrolly_w(uint8_t data)414 void snk_state::snk_bg_scrolly_w(uint8_t data)
415 {
416 	m_bg_scrolly = (m_bg_scrolly & ~0xff) | data;
417 }
418 
snk_sp16_scrollx_w(uint8_t data)419 void snk_state::snk_sp16_scrollx_w(uint8_t data)
420 {
421 	m_sp16_scrollx = (m_sp16_scrollx & ~0xff) | data;
422 }
423 
snk_sp16_scrolly_w(uint8_t data)424 void snk_state::snk_sp16_scrolly_w(uint8_t data)
425 {
426 	m_sp16_scrolly = (m_sp16_scrolly & ~0xff) | data;
427 }
428 
snk_sp32_scrollx_w(uint8_t data)429 void snk_state::snk_sp32_scrollx_w(uint8_t data)
430 {
431 	m_sp32_scrollx = (m_sp32_scrollx & ~0xff) | data;
432 }
433 
snk_sp32_scrolly_w(uint8_t data)434 void snk_state::snk_sp32_scrolly_w(uint8_t data)
435 {
436 	m_sp32_scrolly = (m_sp32_scrolly & ~0xff) | data;
437 }
438 
snk_sprite_split_point_w(uint8_t data)439 void snk_state::snk_sprite_split_point_w(uint8_t data)
440 {
441 	m_sprite_split_point = data;
442 }
443 
444 
marvins_palette_bank_w(uint8_t data)445 void snk_state::marvins_palette_bank_w(uint8_t data)
446 {
447 	m_bg_tilemap->set_palette_offset(data & 0x70);
448 	m_fg_tilemap->set_palette_offset((data & 0x07) << 4);
449 }
450 
marvins_flipscreen_w(uint8_t data)451 void snk_state::marvins_flipscreen_w(uint8_t data)
452 {
453 	flip_screen_set(data & 0x80);
454 
455 	// other bits unknown
456 }
457 
sgladiat_flipscreen_w(uint8_t data)458 void snk_state::sgladiat_flipscreen_w(uint8_t data)
459 {
460 	flip_screen_set(data & 0x80);
461 
462 	m_bg_tilemap->set_palette_offset(((data & 0xf) ^ 8) << 4);
463 
464 	// other bits unknown
465 }
466 
hal21_flipscreen_w(uint8_t data)467 void snk_state::hal21_flipscreen_w(uint8_t data)
468 {
469 	flip_screen_set(data & 0x80);
470 
471 	m_bg_tilemap->set_palette_offset(((data & 0xf) ^ 8) << 4);
472 	if (m_bg_tile_offset != ((data & 0x20) << 3))
473 	{
474 		m_bg_tile_offset = (data & 0x20) << 3;
475 		m_bg_tilemap->mark_all_dirty();
476 	}
477 
478 	// other bits unknown
479 }
480 
marvins_scroll_msb_w(uint8_t data)481 void snk_state::marvins_scroll_msb_w(uint8_t data)
482 {
483 	m_bg_scrollx =   (m_bg_scrollx   & 0xff) | ((data & 0x04) << 6);
484 	m_fg_scrollx =   (m_fg_scrollx   & 0xff) | ((data & 0x02) << 7);
485 	m_sp16_scrollx = (m_sp16_scrollx & 0xff) | ((data & 0x01) << 8);
486 }
487 
jcross_scroll_msb_w(uint8_t data)488 void snk_state::jcross_scroll_msb_w(uint8_t data)
489 {
490 	m_bg_scrolly =   (m_bg_scrolly   & 0xff) | ((data & 0x10) << 4);
491 	m_sp16_scrolly = (m_sp16_scrolly & 0xff) | ((data & 0x08) << 5);
492 	m_bg_scrollx =   (m_bg_scrollx   & 0xff) | ((data & 0x02) << 7);
493 	m_sp16_scrollx = (m_sp16_scrollx & 0xff) | ((data & 0x01) << 8);
494 }
495 
sgladiat_scroll_msb_w(uint8_t data)496 void snk_state::sgladiat_scroll_msb_w(uint8_t data)
497 {
498 	m_bg_scrollx =   (m_bg_scrollx   & 0xff) | ((data & 0x02) << 7);
499 	m_sp16_scrollx = (m_sp16_scrollx & 0xff) | ((data & 0x01) << 8);
500 }
501 
aso_videoattrs_w(uint8_t data)502 void snk_state::aso_videoattrs_w(uint8_t data)
503 {
504 	/*
505 	    video attributes:
506 	    X-------
507 	    -X------
508 	    --X-----    flip screen
509 	    ---X----    scrolly MSB (background)
510 	    ----X---    scrolly MSB (sprites)
511 	    -----X--
512 	    ------X-    scrollx MSB (background)
513 	    -------X    scrollx MSB (sprites)
514 	*/
515 
516 
517 	flip_screen_set(data & 0x20);
518 
519 	m_bg_scrolly =   (m_bg_scrolly   & 0xff) | ((data & 0x10) << 4);
520 	m_sp16_scrolly = (m_sp16_scrolly & 0xff) | ((data & 0x08) << 5);
521 	m_bg_scrollx =   (m_bg_scrollx   & 0xff) | ((data & 0x02) << 7);
522 	m_sp16_scrollx = (m_sp16_scrollx & 0xff) | ((data & 0x01) << 8);
523 }
524 
tnk3_videoattrs_w(uint8_t data)525 void snk_state::tnk3_videoattrs_w(uint8_t data)
526 {
527 	/*
528 	    video attributes:
529 	    X-------    flip screen
530 	    -X------    character bank (for text layer)
531 	    --X-----
532 	    ---X----    scrolly MSB (background)
533 	    ----X---    scrolly MSB (sprites)
534 	    -----X--
535 	    ------X-    scrollx MSB (background)
536 	    -------X    scrollx MSB (sprites)
537 	*/
538 
539 
540 	flip_screen_set(data & 0x80);
541 
542 	if (m_tx_tile_offset != ((data & 0x40) << 2))
543 	{
544 		m_tx_tile_offset = (data & 0x40) << 2;
545 		m_tx_tilemap->mark_all_dirty();
546 	}
547 
548 	m_bg_scrolly =   (m_bg_scrolly   & 0xff) | ((data & 0x10) << 4);
549 	m_sp16_scrolly = (m_sp16_scrolly & 0xff) | ((data & 0x08) << 5);
550 	m_bg_scrollx =   (m_bg_scrollx   & 0xff) | ((data & 0x02) << 7);
551 	m_sp16_scrollx = (m_sp16_scrollx & 0xff) | ((data & 0x01) << 8);
552 }
553 
aso_bg_bank_w(uint8_t data)554 void snk_state::aso_bg_bank_w(uint8_t data)
555 {
556 	m_bg_tilemap->set_palette_offset(((data & 0xf) ^ 8) << 4);
557 	if (m_bg_tile_offset != ((data & 0x30) << 4))
558 	{
559 		m_bg_tile_offset = (data & 0x30) << 4;
560 		m_bg_tilemap->mark_all_dirty();
561 	}
562 }
563 
ikari_bg_scroll_msb_w(uint8_t data)564 void snk_state::ikari_bg_scroll_msb_w(uint8_t data)
565 {
566 	m_bg_scrollx = (m_bg_scrollx & 0xff) | ((data & 0x02) << 7);
567 	m_bg_scrolly = (m_bg_scrolly & 0xff) | ((data & 0x01) << 8);
568 }
569 
ikari_sp_scroll_msb_w(uint8_t data)570 void snk_state::ikari_sp_scroll_msb_w(uint8_t data)
571 {
572 	m_sp32_scrollx = (m_sp32_scrollx & 0xff) | ((data & 0x20) << 3);
573 	m_sp16_scrollx = (m_sp16_scrollx & 0xff) | ((data & 0x10) << 4);
574 	m_sp32_scrolly = (m_sp32_scrolly & 0xff) | ((data & 0x08) << 5);
575 	m_sp16_scrolly = (m_sp16_scrolly & 0xff) | ((data & 0x04) << 6);
576 }
577 
ikari_unknown_video_w(uint8_t data)578 void snk_state::ikari_unknown_video_w(uint8_t data)
579 {
580 	/* meaning of 0xc980 uncertain.
581 	   Normally 0x20, ikaria/ikarijp sets it to 0x31 during test mode.
582 	   Changing char bank is necessary to fix the display during the
583 	   hard flags test and the test grid.
584 	   Changing palette bank is necessary to fix colors in test mode. */
585 
586 
587 	if (data != 0x20 && // normal
588 		data != 0x31 && // ikari test
589 		data != 0xaa)   // victroad spurious during boot
590 		popmessage("attrs %02x contact MAMEDEV", data);
591 
592 	m_tx_tilemap->set_palette_offset((data & 0x01) << 4);
593 	if (m_tx_tile_offset != ((data & 0x10) << 4))
594 	{
595 		m_tx_tile_offset = (data & 0x10) << 4;
596 		m_tx_tilemap->mark_all_dirty();
597 	}
598 }
599 
gwar_tx_bank_w(uint8_t data)600 void snk_state::gwar_tx_bank_w(uint8_t data)
601 {
602 	m_tx_tilemap->set_palette_offset((data & 0xf) << 4);
603 	if (m_tx_tile_offset != ((data & 0x30) << 4))
604 	{
605 		m_tx_tile_offset = (data & 0x30) << 4;
606 		m_tx_tilemap->mark_all_dirty();
607 	}
608 
609 	if (m_is_psychos)
610 		m_bg_tilemap->set_palette_offset((data & 0x80));
611 }
612 
gwar_videoattrs_w(uint8_t data)613 void snk_state::gwar_videoattrs_w(uint8_t data)
614 {
615 	flip_screen_set(data & 0x04);
616 
617 	m_sp32_scrollx = (m_sp32_scrollx & 0xff) | ((data & 0x80) << 1);
618 	m_sp16_scrollx = (m_sp16_scrollx & 0xff) | ((data & 0x40) << 2);
619 	m_sp32_scrolly = (m_sp32_scrolly & 0xff) | ((data & 0x20) << 3);
620 	m_sp16_scrolly = (m_sp16_scrolly & 0xff) | ((data & 0x10) << 4);
621 	m_bg_scrollx =   (m_bg_scrollx   & 0xff) | ((data & 0x02) << 7);
622 	m_bg_scrolly =   (m_bg_scrolly   & 0xff) | ((data & 0x01) << 8);
623 }
624 
gwara_videoattrs_w(uint8_t data)625 void snk_state::gwara_videoattrs_w(uint8_t data)
626 {
627 	flip_screen_set(data & 0x10);
628 
629 	m_bg_scrollx =   (m_bg_scrollx   & 0xff) | ((data & 0x02) << 7);
630 	m_bg_scrolly =   (m_bg_scrolly   & 0xff) | ((data & 0x01) << 8);
631 }
632 
gwara_sp_scroll_msb_w(uint8_t data)633 void snk_state::gwara_sp_scroll_msb_w(uint8_t data)
634 {
635 	m_sp32_scrollx = (m_sp32_scrollx & 0xff) | ((data & 0x20) << 3);
636 	m_sp16_scrollx = (m_sp16_scrollx & 0xff) | ((data & 0x10) << 4);
637 	m_sp32_scrolly = (m_sp32_scrolly & 0xff) | ((data & 0x08) << 5);
638 	m_sp16_scrolly = (m_sp16_scrolly & 0xff) | ((data & 0x04) << 6);
639 }
640 
tdfever_sp_scroll_msb_w(uint8_t data)641 void snk_state::tdfever_sp_scroll_msb_w(uint8_t data)
642 {
643 	m_sp32_scrolly = (m_sp32_scrolly & 0xff) | ((data & 0x80) << 1);
644 	m_sp32_scrollx = (m_sp32_scrollx & 0xff) | ((data & 0x40) << 2);
645 }
646 
tdfever_spriteram_w(offs_t offset,uint8_t data)647 void snk_state::tdfever_spriteram_w(offs_t offset, uint8_t data)
648 {
649 	/*  partial updates avoid flickers in the fsoccer radar. */
650 	if (offset < 0x80 && m_spriteram[offset] != data)
651 	{
652 		int vpos = m_screen->vpos();
653 
654 		if (vpos > 0)
655 			m_screen->update_partial(vpos - 1);
656 	}
657 
658 	m_spriteram[offset] = data;
659 }
660 
661 /**************************************************************************************/
662 
marvins_draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect,const int scrollx,const int scrolly,const int from,const int to)663 void snk_state::marvins_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, const int scrollx, const int scrolly, const int from, const int to)
664 {
665 	gfx_element *gfx = m_gfxdecode->gfx(3);
666 	const uint8_t *source, *finish;
667 
668 	source = m_spriteram + from*4;
669 	finish = m_spriteram + to*4;
670 
671 	while( source<finish )
672 	{
673 		int attributes = source[3]; /* Y?F? CCCC */
674 		int tile_number = source[1];
675 		int sx =  scrollx + 301 - 15 - source[2] + ((attributes&0x80)?256:0);
676 		int sy = -scrolly - 8 + source[0];
677 		int color = attributes&0xf;
678 		int flipy = (attributes&0x20);
679 		int flipx = 0;
680 
681 		if (flip_screen())
682 		{
683 			sx = 89 - 16 - sx;
684 			sy = 262 - 16 - sy;
685 			flipx = !flipx;
686 			flipy = !flipy;
687 		}
688 
689 		sx &= 0x1ff;
690 		sy &= 0xff;
691 		if (sx > 512-16) sx -= 512;
692 		if (sy > 256-16) sy -= 256;
693 
694 		gfx->transtable(bitmap,cliprect,
695 			tile_number,
696 			color,
697 			flipx, flipy,
698 			sx, sy,
699 			m_drawmode_table);
700 
701 		source+=4;
702 	}
703 }
704 
705 
tnk3_draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect,const int xscroll,const int yscroll)706 void snk_state::tnk3_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, const int xscroll, const int yscroll)
707 {
708 	uint8_t *spriteram = m_spriteram;
709 	gfx_element *gfx = m_gfxdecode->gfx(2);
710 	const int size = gfx->width();
711 	int tile_number, attributes, color, sx, sy;
712 	int xflip,yflip;
713 	int offs;
714 
715 	/* jcross and sgladiat have only 25 sprites, the others 50 */
716 
717 	/* jcross has 256 tiles, attribute bit 6 is unused and bit 5 is y-flip */
718 	/* sgladiat and tnk3 have 512 tiles, bit 6 is bank and bit 5 is y-flip */
719 	/* athena has 1024 tiles, bit 6 and bit 5 are bank */
720 
721 	for (offs = 0; offs < m_num_sprites*4; offs += 4)
722 	{
723 		tile_number = spriteram[offs+1];
724 		attributes  = spriteram[offs+3];
725 		color = attributes & 0xf;
726 		sx =  xscroll + 301 - size - spriteram[offs+2];
727 		sy = -yscroll + 7 - size + spriteram[offs];
728 		sx += (attributes & 0x80) << 1;
729 		sy += (attributes & 0x10) << 4;
730 		xflip = 0;
731 		yflip = 0;
732 
733 		if (gfx->elements() > 256)  // all except jcross
734 		{
735 			tile_number |= (attributes & 0x40) << 2;
736 		}
737 
738 		if (gfx->elements() > 512)  // athena
739 		{
740 			tile_number |= (attributes & 0x20) << 4;
741 		}
742 		else    // all others
743 		{
744 			yflip = attributes & 0x20;
745 		}
746 
747 		if (flip_screen())
748 		{
749 			sx = 89 - size - sx;    // this causes slight misalignment in tnk3 but is correct for athena and fitegolf
750 			sy = 262 - size - sy;
751 			xflip = !xflip;
752 			yflip = !yflip;
753 		}
754 
755 		sx &= 0x1ff;
756 		sy &= m_yscroll_mask;    // sgladiat apparently has only 256 pixels of vertical scrolling range
757 		if (sx > 512-size) sx -= 512;
758 		if (sy > (m_yscroll_mask+1)-size) sy -= (m_yscroll_mask+1);
759 
760 		gfx->transtable(bitmap,cliprect,
761 				tile_number,
762 				color,
763 				xflip,yflip,
764 				sx,sy,
765 				m_drawmode_table);
766 	}
767 }
768 
769 
ikari_draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect,const int start,const int xscroll,const int yscroll,const uint8_t * source,const int gfxnum)770 void snk_state::ikari_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, const int start, const int xscroll, const int yscroll, const uint8_t *source, const int gfxnum )
771 {
772 	gfx_element *gfx = m_gfxdecode->gfx(gfxnum);
773 	const int size = gfx->width();
774 	int tile_number, attributes, color, sx, sy;
775 	int which, finish;
776 
777 	finish = (start+25)*4;
778 
779 	for (which = start*4; which < finish; which += 4)
780 	{
781 		tile_number = source[which+1];
782 		attributes  = source[which+3];
783 		color = attributes & 0xf;
784 		sx =  xscroll + 300 - size - source[which+2];
785 		sy = -yscroll + 7 - size + source[which];
786 		sx += (attributes & 0x80) << 1;
787 		sy += (attributes & 0x10) << 4;
788 
789 		switch (size)
790 		{
791 			case 16:
792 				tile_number |= (attributes & 0x60) << 3;
793 				break;
794 
795 			case 32:
796 				tile_number |= (attributes & 0x40) << 2;
797 				break;
798 		}
799 
800 		sx &= 0x1ff;
801 		sy &= 0x1ff;
802 		if (sx > 512-size) sx -= 512;
803 		if (sy > 512-size) sy -= 512;
804 
805 		gfx->transtable(bitmap,cliprect,
806 				tile_number,
807 				color,
808 				0,0,
809 				sx,sy,
810 				m_drawmode_table);
811 	}
812 }
813 
814 /**************************************************************/
815 
816 /*
817 Sprite Format
818 -------------
819 byte0: y offset
820 byte1: tile number
821 byte2: x offset
822 byte3: attributes
823 
824     32x32 attributes:
825 
826     76543210
827     ----xxxx (color)
828     ---x---- (y offset bit8)
829     -xx----- (bank number)
830     x------- (x offset bit8)
831 
832     16x16 attributes:
833 
834     76543210
835     -----xxx (color)
836     ---x---- (y offset bit8)
837     -xx-x--- (bank number)
838     x------- (x offset bit8)
839 */
tdfever_draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect,const int xscroll,const int yscroll,const uint8_t * source,const int gfxnum,const int hw_xflip,const int from,const int to)840 void snk_state::tdfever_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect,   const int xscroll, const int yscroll, const uint8_t *source, const int gfxnum,
841 										const int hw_xflip, const int from, const int to)
842 {
843 	gfx_element *gfx = m_gfxdecode->gfx(gfxnum);
844 	const int size = gfx->width();
845 	int tile_number, attributes, sx, sy, color;
846 	int which;
847 	int flipx, flipy;
848 
849 	for(which = from*4; which < to*4; which+=4)
850 	{
851 		tile_number = source[which+1];
852 		attributes  = source[which+3];
853 		color = attributes & 0x0f;
854 		sx = -xscroll - 9 + source[which+2];
855 		sy = -yscroll + 1 - size + source[which];
856 		sx += (attributes & 0x80) << 1;
857 		sy += (attributes & 0x10) << 4;
858 
859 		switch (size)
860 		{
861 			case 16:
862 				tile_number |= ((attributes & 0x08) << 5) | ((attributes & 0x60) << 4);
863 				color &= 7; // attribute bit 3 is used for bank select
864 				if (from == 0)
865 					color |= 8; // low priority sprites use the other palette bank
866 				break;
867 
868 			case 32:
869 				tile_number |= (attributes & 0x60) << 3;
870 				break;
871 		}
872 
873 		flipx = hw_xflip;
874 		flipy = 0;
875 
876 		if (hw_xflip)
877 			sx = 495 - size - sx;
878 
879 		if (flip_screen())
880 		{
881 			sx = 495 - size - sx;
882 			sy = 258 - size - sy;
883 			flipx = !flipx;
884 			flipy = !flipy;
885 		}
886 
887 		sx &= 0x1ff;
888 		sy &= 0x1ff;
889 		if (sx > 512-size) sx -= 512;
890 		if (sy > 512-size) sy -= 512;
891 
892 		gfx->transtable(bitmap,cliprect,
893 				tile_number,
894 				color,
895 				flipx,flipy,
896 				sx,sy,
897 				m_drawmode_table);
898 	}
899 }
900 
901 /**************************************************************/
902 
screen_update_marvins(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)903 uint32_t snk_state::screen_update_marvins(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
904 {
905 	m_bg_tilemap->set_scrollx(0, m_bg_scrollx);
906 	m_bg_tilemap->set_scrolly(0, m_bg_scrolly);
907 	m_fg_tilemap->set_scrollx(0, m_fg_scrollx);
908 	m_fg_tilemap->set_scrolly(0, m_fg_scrolly);
909 
910 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
911 	marvins_draw_sprites(bitmap, cliprect, m_sp16_scrollx, m_sp16_scrolly, 0, m_sprite_split_point>>2);
912 	m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
913 	marvins_draw_sprites(bitmap, cliprect, m_sp16_scrollx, m_sp16_scrolly, m_sprite_split_point>>2, 25);
914 	m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
915 
916 	return 0;
917 }
918 
919 
screen_update_tnk3(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)920 uint32_t snk_state::screen_update_tnk3(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
921 {
922 	m_bg_tilemap->set_scrollx(0, m_bg_scrollx);
923 	m_bg_tilemap->set_scrolly(0, m_bg_scrolly);
924 
925 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
926 	tnk3_draw_sprites(bitmap, cliprect, m_sp16_scrollx, m_sp16_scrolly);
927 	m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
928 
929 	return 0;
930 }
931 
screen_update_fitegolf2(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)932 uint32_t snk_state::screen_update_fitegolf2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
933 {
934 	m_bg_tilemap->set_scrollx(0, m_bg_scrollx);
935 	m_bg_tilemap->set_scrolly(0, m_bg_scrolly);
936 
937 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
938 	tnk3_draw_sprites(bitmap, cliprect, m_sp16_scrollx+1, m_sp16_scrolly); // needs an extra offset?? neither this or fitegolf actually write to sprite offset registers tho?
939 	m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
940 
941 	return 0;
942 }
943 
944 
945 
screen_update_ikari(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)946 uint32_t snk_state::screen_update_ikari(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
947 {
948 	m_bg_tilemap->set_scrollx(0, m_bg_scrollx);
949 	m_bg_tilemap->set_scrolly(0, m_bg_scrolly);
950 
951 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
952 
953 	ikari_draw_sprites(bitmap, cliprect,  0, m_sp16_scrollx, m_sp16_scrolly, m_spriteram + 0x800, 2 );
954 	ikari_draw_sprites(bitmap, cliprect,  0, m_sp32_scrollx, m_sp32_scrolly, m_spriteram,         3 );
955 	ikari_draw_sprites(bitmap, cliprect, 25, m_sp16_scrollx, m_sp16_scrolly, m_spriteram + 0x800, 2 );
956 
957 	m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
958 	return 0;
959 }
960 
961 
screen_update_gwar(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)962 uint32_t snk_state::screen_update_gwar(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
963 {
964 	m_bg_tilemap->set_scrollx(0, m_bg_scrollx);
965 	m_bg_tilemap->set_scrolly(0, m_bg_scrolly);
966 
967 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
968 
969 	tdfever_draw_sprites(bitmap, cliprect, m_sp16_scrollx, m_sp16_scrolly, m_spriteram + 0x800, 2, 0, 0, m_sprite_split_point );
970 	tdfever_draw_sprites(bitmap, cliprect, m_sp32_scrollx, m_sp32_scrolly, m_spriteram,         3, 0, 0, 32 );
971 	tdfever_draw_sprites(bitmap, cliprect, m_sp16_scrollx, m_sp16_scrolly, m_spriteram + 0x800, 2, 0, m_sprite_split_point, 64 );
972 
973 	m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
974 
975 	return 0;
976 }
977 
978 
screen_update_tdfever(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)979 uint32_t snk_state::screen_update_tdfever(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
980 {
981 	m_bg_tilemap->set_scrollx(0, m_bg_scrollx);
982 	m_bg_tilemap->set_scrolly(0, m_bg_scrolly);
983 
984 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
985 
986 	tdfever_draw_sprites(bitmap, cliprect, m_sp32_scrollx, m_sp32_scrolly, m_spriteram, 2, 1, 0, 32 );
987 
988 	m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
989 
990 	return 0;
991 }
992