1 // license:BSD-3-Clause
2 // copyright-holders:Luca Elia
3 /***************************************************************************
4 
5                             -= Jaleco Driving Games =-
6 
7                     driver by   Luca Elia (l.elia@tin.it)
8 
9 
10 Note:   if MAME_DEBUG is defined, pressing Z or X with:
11 
12         Q,W,E       shows scroll 0,1,2
13         R,T         shows road 0,1
14         A,S,D,F     shows sprites with priority 0,1,2,3
15         X           shows some info on each sprite
16         M           disables sprites zooming
17         U           toggles the display of some hardware registers'
18                     values ($80000/2/4/6)
19 
20         Keys can be used together!
21         Additionally, layers can be disabled, writing to $82400
22         (fake video register):
23 
24             ---- ---- --54 ----     Enable Road 1,0
25             ---- ---- ---- 3---     Enable Sprites
26             ---- ---- ---- -210     Enable Scroll 2,1,0
27 
28         0 is the same as 0x3f
29 
30 [ 3 Scrolling Layers ]
31 
32     see ms1_tmap.cpp
33 
34 [ 2 Road Layers ]
35 
36     Each of the 256 (not all visible) lines of the screen
37     can display any of the lines of gfx in ROM, which are
38     larger than the screen and can therefore be scrolled
39 
40                                     Cisco Heat              F1 GP Star
41                 Line Width          1024                    1024
42                 Zoom                No                      Yes
43 
44 [ 256 Sprites ]
45 
46     Sprites are made of several 16x16 tiles (up to 256x256 pixels)
47     and can be zoomed in and out. See below for sprite RAM format.
48 
49 ***************************************************************************/
50 
51 #include "emu.h"
52 #include "includes/cischeat.h"
53 
54 
55 #define cischeat_tmap_DRAW(_n_) \
56 	if ( (m_tmap[_n_]).found() && (active_layers1 & (1 << _n_) ) ) \
57 	{ \
58 		m_tmap[_n_]->draw(screen, bitmap, cliprect, flag, 0 ); \
59 		flag = 0; \
60 	}
61 
62 
63 /***************************************************************************
64 
65 
66                             Video Hardware Init
67 
68 
69 ***************************************************************************/
70 
prepare_shadows()71 void cischeat_state::prepare_shadows()
72 {
73 	int i;
74 	for (i = 0;i < 16;i++)
75 		m_drawmode_table[i] = DRAWMODE_SOURCE;
76 
77 	m_drawmode_table[ 0] = DRAWMODE_SHADOW;
78 	m_drawmode_table[15] = DRAWMODE_NONE;
79 }
80 
video_start()81 void cischeat_state::video_start()
82 {
83 	m_spriteram = &m_ram[0x8000/2];
84 
85 	m_active_layers = 0;
86 
87 	prepare_shadows();
88 
89 	m_motor_value = 0;
90 	m_io_value = 0;
91 }
92 
video_start()93 void wildplt_state::video_start()
94 {
95 	cischeat_state::video_start();
96 	m_buffer_spriteram = &m_ram[0x8000/2];
97 	m_allocated_spriteram = std::make_unique<uint16_t[]>(0x1000/2);
98 	m_spriteram = m_allocated_spriteram.get();
99 }
100 
sprite_dma_w(offs_t offset,uint16_t data,uint16_t mem_mask)101 void wildplt_state::sprite_dma_w(offs_t offset, uint16_t data, uint16_t mem_mask)
102 {
103 	// bit 13: 0 -> 1 transition triggers a sprite DMA
104 	if(data & 0x2000 && (m_sprite_dma_reg & 0x2000) == 0)
105 	{
106 		for(int i=0;i<0x1000/2;i++)
107 			m_spriteram[i] = m_buffer_spriteram[i];
108 	}
109 
110 	// other bits unknown
111 	COMBINE_DATA(&m_sprite_dma_reg);
112 }
113 
114 /***************************************************************************
115 
116 
117                         Hardware registers access
118 
119 
120 ***************************************************************************/
121 
122 /*
123     F1 GP Star has a real pedal, while Cisco Heat's is connected to
124     a switch. The Former game stores, during boot, the value that
125     corresponds to the pedal not pressed, and compares against it:
126 
127     The value returned must decrease when the pedal is pressed.
128 */
129 
130 /**************************************************************************
131                                 Big Run
132 **************************************************************************/
133 
bigrun_ip_select_r()134 uint16_t cischeat_state::bigrun_ip_select_r()
135 {
136 	switch (m_ip_select & 0x3)
137 	{
138 		case 0 : return ioport("IN6")->read();      // Driving Wheel
139 		case 1 : return 0xffff;                 // Cockpit: Up / Down Position
140 		case 2 : return 0xffff;                 // Cockpit: Left / Right Position?
141 		case 3 : return ioport("PEDAL")->read();    // Accelerator (Pedal)
142 		default: return 0xffff;
143 	}
144 }
145 
146 
unknown_out_w(uint16_t data)147 void cischeat_state::unknown_out_w(uint16_t data)
148 {
149 	// ?? 91/1/91/1 ...
150 }
151 
152 
motor_out_w(offs_t offset,uint16_t data,uint16_t mem_mask)153 void cischeat_state::motor_out_w(offs_t offset, uint16_t data, uint16_t mem_mask)
154 {
155 	// motor (seat?)
156 	if (ACCESSING_BITS_0_7)
157 		m_leds[2] = (data & 0xff) != m_motor_value ? 1 : 0;
158 	m_motor_value = data & 0xff;
159 }
160 
161 
wheel_out_w(uint16_t data)162 void cischeat_state::wheel_out_w(uint16_t data)
163 {
164 	// motor (wheel?)
165 }
166 
167 
ip_select_w(uint16_t data)168 void cischeat_state::ip_select_w(uint16_t data)
169 {
170 	m_ip_select = data;
171 }
172 
173 
ip_select_plus1_w(uint16_t data)174 void cischeat_state::ip_select_plus1_w(uint16_t data)
175 {
176 	// value above + 1
177 	m_ip_select = data + 1;
178 }
179 
180 
bigrun_comms_w(uint16_t data)181 void cischeat_state::bigrun_comms_w(uint16_t data)
182 {
183 	/* Not sure about this one.. */
184 	m_cpu2->set_input_line(INPUT_LINE_RESET, (data & 2) ? ASSERT_LINE : CLEAR_LINE);
185 	m_cpu3->set_input_line(INPUT_LINE_RESET, (data & 2) ? ASSERT_LINE : CLEAR_LINE);
186 	m_soundcpu->set_input_line(INPUT_LINE_RESET, (data & 1) ? ASSERT_LINE : CLEAR_LINE);
187 }
188 
189 // TODO: fake port, never written to my knowledge!
active_layers_w(offs_t offset,uint16_t data,uint16_t mem_mask)190 void cischeat_state::active_layers_w(offs_t offset, uint16_t data, uint16_t mem_mask)
191 {
192 	COMBINE_DATA(&m_active_layers);
193 }
194 
195 
196 /**************************************************************************
197                                 Cisco Heat
198 **************************************************************************/
199 
cischeat_ip_select_r()200 uint16_t cischeat_state::cischeat_ip_select_r()
201 {
202 	switch (m_ip_select & 0x3)
203 	{
204 		case 0 : return ioport("IN6")->read();  // Driving Wheel
205 		case 1 : return ~0;                 // Cockpit: Up / Down Position?
206 		case 2 : return ~0;                 // Cockpit: Left / Right Position?
207 		default: return ~0;
208 	}
209 }
210 
211 
cischeat_soundlatch_w(uint16_t data)212 void cischeat_state::cischeat_soundlatch_w(uint16_t data)
213 {
214 	/* Sound CPU: reads latch during int 4, and stores command */
215 	m_soundlatch->write(data);
216 	m_soundcpu->set_input_line(4, HOLD_LINE);
217 }
218 
219 
cischeat_comms_w(uint16_t data)220 void cischeat_state::cischeat_comms_w(uint16_t data)
221 {
222 	/* Not sure about this one.. */
223 	m_cpu2->set_input_line(INPUT_LINE_RESET, (data & 2) ? ASSERT_LINE : CLEAR_LINE);
224 	m_cpu3->set_input_line(INPUT_LINE_RESET, (data & 2) ? ASSERT_LINE : CLEAR_LINE);
225 	m_soundcpu->set_input_line(INPUT_LINE_RESET, (data & 1) ? ASSERT_LINE : CLEAR_LINE);
226 }
227 
228 
229 
230 /**************************************************************************
231                             F1 GrandPrix Star
232 **************************************************************************/
233 
f1gpstar_wheel_r()234 uint16_t cischeat_state::f1gpstar_wheel_r()
235 {
236 	return (ioport("PEDAL")->read() & 0xff) + ((ioport("IN5")->read() & 0xff)<<8);
237 }
238 
239 
f1gpstr2_ioready_r()240 uint16_t cischeat_state::f1gpstr2_ioready_r()
241 {
242 	return (m_f1gpstr2_ioready[0]&1) ? 0xff : 0xf0;
243 }
244 
245 
246 /**************************************************************************
247                             Wild Pilot
248 **************************************************************************/
249 
250 
f1gpstar_motor_w(offs_t offset,uint16_t data,uint16_t mem_mask)251 void cischeat_state::f1gpstar_motor_w(offs_t offset, uint16_t data, uint16_t mem_mask)
252 {
253 	// "shudder" motors, leds
254 	if (ACCESSING_BITS_0_7)
255 	{
256 		machine().bookkeeping().coin_counter_w(0, data & 0x01);
257 		machine().bookkeeping().coin_counter_w(1, data & 0x02);
258 		m_leds[0] = BIT(data, 2);   // start button
259 		m_leds[1] = BIT(data, 5);   // ?
260 		// wheel | seat motor
261 		m_leds[2] = BIT(data, 3) | BIT(data, 4);
262 	}
263 }
264 
265 
f1gpstar_soundint_w(uint16_t data)266 void cischeat_state::f1gpstar_soundint_w(uint16_t data)
267 {
268 	/* $80008 and $80018 usually written in sequence, but not always */
269 	m_soundcpu->set_input_line(4, HOLD_LINE);
270 }
271 
272 
f1gpstar_comms_w(uint16_t data)273 void cischeat_state::f1gpstar_comms_w(uint16_t data)
274 {
275 	/* Not sure about this one. Values: $10 then 0, $7 then 0 */
276 	m_cpu2->set_input_line(INPUT_LINE_RESET, (data & 1) ? ASSERT_LINE : CLEAR_LINE);
277 	m_cpu3->set_input_line(INPUT_LINE_RESET, (data & 2) ? ASSERT_LINE : CLEAR_LINE);
278 	m_soundcpu->set_input_line(INPUT_LINE_RESET, (data & 4) ? ASSERT_LINE : CLEAR_LINE);
279 }
280 
281 
f1gpstr2_io_w(offs_t offset,uint16_t data,uint16_t mem_mask)282 void cischeat_state::f1gpstr2_io_w(offs_t offset, uint16_t data, uint16_t mem_mask)
283 {
284 	if (ACCESSING_BITS_0_7)
285 	{
286 		if ((m_io_value & 4) && ((data & 4) == 0))
287 			m_cpu5->set_input_line(4, HOLD_LINE);
288 		if ((m_io_value & 2) && ((data & 2) == 0))
289 			m_cpu5->set_input_line(2, HOLD_LINE);
290 		m_io_value = data & 0xff;
291 	}
292 }
293 
294 
295 
296 
297 /***************************************************************************
298 
299 
300                                 Road Drawing
301 
302 
303 ***************************************************************************/
304 
305 /* horizontal size of 1 line and 1 tile of the road */
306 #define X_SIZE (1024)
307 #define TILE_SIZE (64)
308 
309 
310 /**************************************************************************
311 
312                         Cisco Heat road format
313 
314 
315     Offset:     Bits:                   Value:
316 
317     00.w                                Code
318 
319     02.w                                X Scroll
320 
321     04.w        fedc ---- ---- ----     unused?
322                 ---- ba98 ---- ----     Priority
323                 ---- ---- 76-- ----     unused?
324                 ---- ---- --54 3210     Color
325 
326     06.w                                Unused
327 
328 **************************************************************************/
329 
330 /*  Draw the road in the given bitmap. The priority1 and priority2 parameters
331     specify the range of lines to draw  */
332 
cischeat_draw_road(bitmap_ind16 & bitmap,const rectangle & cliprect,int road_num,int priority1,int priority2,int transparency)333 void cischeat_state::cischeat_draw_road(bitmap_ind16 &bitmap, const rectangle &cliprect, int road_num, int priority1, int priority2, int transparency)
334 {
335 	int curr_code,sx,sy;
336 	int min_priority, max_priority;
337 
338 	rectangle rect      =   cliprect;
339 	gfx_element *gfx        =   m_gfxdecode->gfx((road_num & 1) ? 2 : 1);
340 
341 	uint16_t *roadram         =   m_roadram[road_num & 1];
342 
343 	int min_y = rect.min_y;
344 	int max_y = rect.max_y;
345 
346 	int max_x = rect.max_x;
347 
348 	if (priority1 < priority2)  {   min_priority = priority1;   max_priority = priority2; }
349 	else                        {   min_priority = priority2;   max_priority = priority1; }
350 
351 	/* Move the priority values in place */
352 	min_priority = (min_priority & 7) * 0x100;
353 	max_priority = (max_priority & 7) * 0x100;
354 
355 	/* Let's draw from the top to the bottom of the visible screen */
356 	for (sy = min_y ; sy <= max_y ; sy ++)
357 	{
358 		int code    = roadram[ sy * 4 + 0 ];
359 		int xscroll = roadram[ sy * 4 + 1 ];
360 		int attr    = roadram[ sy * 4 + 2 ];
361 
362 		/* high byte is a priority information */
363 		if ( ((attr & 0x700) < min_priority) || ((attr & 0x700) > max_priority) )
364 			continue;
365 
366 		/* line number converted to tile number (each tile is TILE_SIZE x 1) */
367 		code = code * (X_SIZE/TILE_SIZE);
368 
369 		xscroll %= X_SIZE;
370 		curr_code = code + xscroll/TILE_SIZE;
371 
372 		for (sx = -(xscroll%TILE_SIZE) ; sx <= max_x ; sx +=TILE_SIZE)
373 		{
374 			gfx->transpen(bitmap,rect,
375 					curr_code++,
376 					attr,
377 					0,0,
378 					sx,sy,
379 					transparency ? 15 : -1);
380 
381 			/* wrap around */
382 			if (curr_code%(X_SIZE/TILE_SIZE)==0)    curr_code = code;
383 		}
384 	}
385 
386 }
387 
388 
389 
390 /**************************************************************************
391 
392                         F1 GrandPrix Star road format
393 
394     Offset:     Bits:                   Value:
395 
396     00.w        fedc ---- ---- ----     Priority
397                 ---- ba98 7654 3210     X Scroll (After Zoom)
398 
399     02.w        fedc ba-- ---- ----     unused?
400                 ---- --98 7654 3210     X Zoom
401 
402     04.w        fe-- ---- ---- ----     unused?
403                 --dc ba98 ---- ----     Color
404                 ---- ---- 7654 3210     ?
405 
406     06.w                                Code
407 
408 
409     Imagine an "empty" line, 2 * X_SIZE wide, with the gfx from
410     the ROM - whose original size is X_SIZE - in the middle.
411 
412     Zooming acts on this latter and can shrink it to 1 pixel or
413     widen it to 2 * X_SIZE, while *keeping it centered* in the
414     empty line. Scrolling acts on the resulting line.
415 
416 
417 **************************************************************************/
418 
419 /*  Draw the road in the given bitmap. The priority1 and priority2 parameters
420     specify the range of lines to draw  */
421 
f1gpstar_draw_road(bitmap_ind16 & bitmap,const rectangle & cliprect,int road_num,int priority1,int priority2,int transparency)422 void cischeat_state::f1gpstar_draw_road(bitmap_ind16 &bitmap, const rectangle &cliprect, int road_num, int priority1, int priority2, int transparency)
423 {
424 	int sx,sy;
425 	int xstart;
426 	int min_priority, max_priority;
427 
428 	rectangle rect      =   cliprect;
429 	gfx_element *gfx        =   m_gfxdecode->gfx((road_num & 1) ? 2 : 1);
430 
431 	uint16_t *roadram         =   m_roadram[road_num & 1];
432 
433 	int min_y = rect.min_y;
434 	int max_y = rect.max_y;
435 
436 	int max_x = rect.max_x << 16;   // use fixed point values (16.16), for accuracy
437 
438 	if (priority1 < priority2)  {   min_priority = priority1;   max_priority = priority2; }
439 	else                        {   min_priority = priority2;   max_priority = priority1; }
440 
441 	/* Move the priority values in place */
442 	min_priority = (min_priority & 7) * 0x1000;
443 	max_priority = (max_priority & 7) * 0x1000;
444 
445 	/* Let's draw from the top to the bottom of the visible screen */
446 	for (sy = min_y ; sy <= max_y ; sy ++)
447 	{
448 		int xscale, xdim;
449 
450 		int xscroll = roadram[ sy * 4 + 0 ];
451 		int xzoom   = roadram[ sy * 4 + 1 ];
452 		int attr    = roadram[ sy * 4 + 2 ];
453 		int code    = roadram[ sy * 4 + 3 ];
454 
455 		/* highest nibble is a priority information */
456 		if ( ((xscroll & 0x7000) < min_priority) || ((xscroll & 0x7000) > max_priority) )
457 			continue;
458 
459 		/* zoom code range: 000-3ff     scale range: 0.0-2.0 */
460 		xscale = ( ((xzoom & 0x3ff)+1) << (16+1) ) / 0x400;
461 
462 		/* line number converted to tile number (each tile is TILE_SIZE x 1) */
463 		code    = code * (X_SIZE/TILE_SIZE);
464 
465 		/* dimension of a tile after zoom */
466 		xdim = TILE_SIZE * xscale;
467 
468 		xscroll %= 2 * X_SIZE;
469 
470 		xstart  = (X_SIZE - xscroll) * 0x10000;
471 		xstart -= (X_SIZE * xscale) / 2;
472 
473 		/* let's approximate to the nearest greater integer value
474 		   to avoid holes in between tiles */
475 		xscale += (1<<16)/TILE_SIZE;
476 
477 		/* Draw the line */
478 		for (sx = xstart ; sx <= max_x ; sx += xdim)
479 		{
480 			gfx->zoom_transpen(bitmap,rect,
481 						code++,
482 						attr >> 8,
483 						0,0,
484 						sx / 0x10000, sy,
485 						xscale, 1 << 16,
486 						transparency ? 15 : -1);
487 
488 			/* stop when the end of the line of gfx is reached */
489 			if ((code % (X_SIZE/TILE_SIZE)) == 0)   break;
490 		}
491 
492 	}
493 }
494 
495 
496 /***************************************************************************
497 
498                 Cisco Heat & F1 GP Star Sprites Drawing
499 
500     Offset: Bits:                   Value:
501 
502     00      fed- ---- ---- ----     unused?
503             ---c ---- ---- ----     Don't display this sprite
504             ---- ba98 ---- ----     unused?
505             ---- ---- 7654 ----     Number of tiles along Y, minus 1 (1-16)
506             ---- ---- ---- 3210     Number of tiles along X, minus 1 (1-16)
507 
508     02/04   fed- ---- ---- ----     unused?
509             ---c ---- ---- ----     Flip X/Y
510             ---- ba9- ---- ----     ? X/Y zoom ?
511             ---- ---8 7654 3210     X/Y zoom
512 
513     06/08   fedc ba-- ---- ----     ? X/Y position ?
514             ---- --98 7654 3210     X/Y position
515 
516     0A                              0 ?
517 
518     0C                              Code
519 
520     0E      fed- ---- ---- ----     unused?
521             ---c ---- ---- ----     Use pen 0 as shadow
522             ---- ba98 ---- ----     Priority
523             ---- ---- 7--- ----     unused?
524             ---- ---- -654 3210     Color
525 
526 ***************************************************************************/
527 
528 #define SHRINK(_org_,_fact_) ( ( ( (_org_) << 16 ) * (_fact_ & 0x01ff) ) / 0x80 )
529 
530 /*  Draw sprites, in the given priority range, to a bitmap.
531 
532     Priorities between 0 and 15 cover sprites whose priority nibble
533     is between 0 and 15. Priorities between 0+16 and 15+16 cover
534     sprites whose priority nibble is between 0 and 15 and whose
535     colour code's high bit is set.  */
536 
cischeat_draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect,int priority1,int priority2)537 void cischeat_state::cischeat_draw_sprites(bitmap_ind16 &bitmap , const rectangle &cliprect, int priority1, int priority2)
538 {
539 	int x, sx, flipx, xzoom, xscale, xdim, xnum, xstart, xend, xinc;
540 	int y, sy, flipy, yzoom, yscale, ydim, ynum, ystart, yend, yinc;
541 	int code, attr, color, size, shadow;
542 
543 	int min_priority, max_priority, high_sprites;
544 
545 	uint16_t      *source =   m_spriteram;
546 	const uint16_t    *finish =   source + 0x1000/2;
547 
548 
549 	/* Move the priority values in place */
550 	high_sprites = (priority1 >= 16) | (priority2 >= 16);
551 	priority1 = (priority1 & 0x0f) * 0x100;
552 	priority2 = (priority2 & 0x0f) * 0x100;
553 
554 	if (priority1 < priority2)  {   min_priority = priority1;   max_priority = priority2; }
555 	else                        {   min_priority = priority2;   max_priority = priority1; }
556 
557 	for (; source < finish; source += 0x10/2 )
558 	{
559 		size    =   source[ 0 ];
560 		if (size & 0x1000)  continue;
561 
562 		/* number of tiles */
563 		xnum    =   ( (size & 0x0f) >> 0 ) + 1;
564 		ynum    =   ( (size & 0xf0) >> 4 ) + 1;
565 
566 		xzoom   =   source[ 1 ];
567 		yzoom   =   source[ 2 ];
568 		flipx   =   xzoom & 0x1000;
569 		flipy   =   yzoom & 0x1000;
570 
571 		sx      =   source[ 3 ];
572 		sy      =   source[ 4 ];
573 		// TODO: was & 0x1ff with 0x200 as sprite wrap sign, looks incorrect with Grand Prix Star
574 		//       during big car on side view in attract mode (a tyre gets stuck on the right of the screen)
575 		//       this arrangement works with both games (otherwise Part 2 gets misaligned bleachers sprites)
576 		sx      =   (sx & 0x7ff);
577 		sy      =   (sy & 0x7ff);
578 		if(sx & 0x400)
579 			sx -= 0x800;
580 		if(sy & 0x400)
581 			sy -= 0x800;
582 
583 		/* use fixed point values (16.16), for accuracy */
584 		sx <<= 16;
585 		sy <<= 16;
586 
587 		/* dimension of a tile after zoom */
588 #ifdef MAME_DEBUG
589 		if ( machine().input().code_pressed(KEYCODE_Z) && machine().input().code_pressed(KEYCODE_M) )
590 		{
591 			xdim    =   16 << 16;
592 			ydim    =   16 << 16;
593 		}
594 		else
595 #endif
596 		{
597 			xdim    =   SHRINK(16,xzoom);
598 			ydim    =   SHRINK(16,yzoom);
599 		}
600 
601 		if ( ( (xdim / 0x10000) == 0 ) || ( (ydim / 0x10000) == 0) )    continue;
602 
603 		/* the y pos passed to the hardware is the that of the last line,
604 		   we need the y pos of the first line  */
605 		sy -= (ydim * ynum);
606 
607 		code    =   source[ 6 ];
608 		attr    =   source[ 7 ];
609 		color   =   attr & 0x007f;
610 		shadow  =   attr & 0x1000;
611 
612 		/* high byte is a priority information */
613 		if ( ((attr & 0x700) < min_priority) || ((attr & 0x700) > max_priority) )
614 			continue;
615 
616 		if ( high_sprites && !(color & 0x80) )
617 			continue;
618 
619 #ifdef MAME_DEBUG
620 if ( (m_debugsprites) && ( ((attr & 0x0300)>>8) != (m_debugsprites-1) ) ) { continue; };
621 #endif
622 
623 		xscale = xdim / 16;
624 		yscale = ydim / 16;
625 
626 
627 		/* let's approximate to the nearest greater integer value
628 		   to avoid holes in between tiles */
629 		if (xscale & 0xffff)    xscale += (1<<16)/16;
630 		if (yscale & 0xffff)    yscale += (1<<16)/16;
631 
632 
633 		if (flipx)  { xstart = xnum-1;  xend = -1;    xinc = -1; }
634 		else        { xstart = 0;       xend = xnum;  xinc = +1; }
635 
636 		if (flipy)  { ystart = ynum-1;  yend = -1;    yinc = -1; }
637 		else        { ystart = 0;       yend = ynum;  yinc = +1; }
638 
639 		m_drawmode_table[ 0] = shadow ? DRAWMODE_SHADOW : DRAWMODE_SOURCE;
640 
641 		for (y = ystart; y != yend; y += yinc)
642 		{
643 			for (x = xstart; x != xend; x += xinc)
644 			{
645 				m_gfxdecode->gfx(0)->zoom_transtable(bitmap,cliprect,code++,color,flipx,flipy,
646 							(sx + x * xdim) / 0x10000, (sy + y * ydim) / 0x10000,
647 							xscale, yscale, m_drawmode_table);
648 			}
649 		}
650 #ifdef MAME_DEBUG
651 #if 0
652 if (machine().input().code_pressed(KEYCODE_X))
653 {   /* Display some info on each sprite */
654 	sprintf(buf, "%04x",attr);
655 	ui_draw_text(buf, sx>>16, sy>>16);
656 }
657 #endif
658 #endif
659 	}   /* end sprite loop */
660 }
661 
662 
663 /***************************************************************************
664 
665                             Big Run Sprites Drawing
666 
667     Offset: Bits:                   Value:
668 
669     00      fed- ---- ---- ----     unused?
670             ---c ---- ---- ----     Don't display this sprite
671             ---- ba98 ---- ----     unused?
672             ---- ---- 7654 ----     Number of tiles along Y, minus 1 (1-16)
673             ---- ---- ---- 3210     Number of tiles along X, minus 1 (1-16)
674 
675     02      fedc ba98 ---- ----     Y zoom
676             ---- ---- 7654 3210     X zoom
677 
678     04/06   fed- ---- ---- ----
679             ---c ---- ---- ----     X/Y flip
680             ---- ba9- ---- ----
681             ---- ---8 7654 3210     X/Y position (signed)
682 
683     08                              ?
684     0A                              ?
685 
686     0C                              Code
687 
688     0E      fed- ---- ---- ----     unused?
689             ---c ---- ---- ----     Use pen 0 as shadow
690             ---- ba98 ---- ----     Priority
691             ---- ---- 76-- ----     unused?
692             ---- ---- --54 3210     Color
693 
694 ***************************************************************************/
695 
bigrun_draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect,int priority1,int priority2)696 void cischeat_state::bigrun_draw_sprites(bitmap_ind16 &bitmap , const rectangle &cliprect, int priority1, int priority2)
697 {
698 	int x, sx, flipx, xzoom, xscale, xdim, xnum, xstart, xend, xinc;
699 	int y, sy, flipy, yzoom, yscale, ydim, ynum, ystart, yend, yinc;
700 	int code, attr, color, size, shadow;
701 
702 	int min_priority, max_priority, high_sprites;
703 
704 	uint16_t      *source =   m_spriteram;
705 	const uint16_t    *finish =   source + 0x1000/2;
706 
707 	/* Move the priority values in place */
708 	high_sprites = (priority1 >= 16) | (priority2 >= 16);
709 	priority1 = (priority1 & 0x0f) * 0x100;
710 	priority2 = (priority2 & 0x0f) * 0x100;
711 
712 	if (priority1 < priority2)  {   min_priority = priority1;   max_priority = priority2; }
713 	else                        {   min_priority = priority2;   max_priority = priority1; }
714 
715 	for (; source < finish; source += 0x10/2 )
716 	{
717 		size    =   source[ 0 ];
718 		if (size & 0x1000)  continue;
719 
720 		/* number of tiles */
721 		xnum    =   ( (size & 0x0f) >> 0 ) + 1;
722 		ynum    =   ( (size & 0xf0) >> 4 ) + 1;
723 
724 		yzoom   =   (source[ 1 ] >> 8) & 0xff;
725 		xzoom   =   (source[ 1 ] >> 0) & 0xff;
726 
727 		sx      =   source[ 2 ];
728 		sy      =   source[ 3 ];
729 		flipx   =   sx & 0x1000;
730 		flipy   =   sy & 0x1000;
731 //      sx      =   (sx & 0x1ff) - (sx & 0x200);
732 //      sy      =   (sy & 0x1ff) - (sy & 0x200);
733 		sx      =   (sx & 0x0ff) - (sx & 0x100);
734 		sy      =   (sy & 0x0ff) - (sy & 0x100);
735 
736 		/* use fixed point values (16.16), for accuracy */
737 		sx <<= 16;
738 		sy <<= 16;
739 
740 		/* dimension of a tile after zoom */
741 #ifdef MAME_DEBUG
742 		if ( machine().input().code_pressed(KEYCODE_Z) && machine().input().code_pressed(KEYCODE_M) )
743 		{
744 			xdim    =   16 << 16;
745 			ydim    =   16 << 16;
746 		}
747 		else
748 #endif
749 		{
750 			xdim    =   SHRINK(16,xzoom);
751 			ydim    =   SHRINK(16,yzoom);
752 		}
753 
754 		if ( ( (xdim / 0x10000) == 0 ) || ( (ydim / 0x10000) == 0) )    continue;
755 
756 //      sy -= (ydim * ynum);
757 
758 		code    =   source[ 6 ];
759 		attr    =   source[ 7 ];
760 		color   =   attr & 0x007f;
761 		shadow  =   attr & 0x1000;
762 
763 		/* high byte is a priority information */
764 		if ( ((attr & 0x700) < min_priority) || ((attr & 0x700) > max_priority) )
765 			continue;
766 
767 		if ( high_sprites && !(color & 0x80) )
768 			continue;
769 
770 #ifdef MAME_DEBUG
771 if ( (m_debugsprites) && ( ((attr & 0x0300)>>8) != (m_debugsprites-1) ) ) { continue; };
772 #endif
773 
774 		xscale = xdim / 16;
775 		yscale = ydim / 16;
776 
777 
778 		/* let's approximate to the nearest greater integer value
779 		   to avoid holes in between tiles */
780 		if (xscale & 0xffff)    xscale += (1<<16)/16;
781 		if (yscale & 0xffff)    yscale += (1<<16)/16;
782 
783 
784 		if (flipx)  { xstart = xnum-1;  xend = -1;    xinc = -1; }
785 		else        { xstart = 0;       xend = xnum;  xinc = +1; }
786 
787 		if (flipy)  { ystart = ynum-1;  yend = -1;    yinc = -1; }
788 		else        { ystart = 0;       yend = ynum;  yinc = +1; }
789 
790 		m_drawmode_table[ 0] = shadow ? DRAWMODE_SHADOW : DRAWMODE_SOURCE;
791 
792 		for (y = ystart; y != yend; y += yinc)
793 		{
794 			for (x = xstart; x != xend; x += xinc)
795 			{
796 				m_gfxdecode->gfx(0)->zoom_transtable(bitmap,cliprect,code++,color,flipx,flipy,
797 							(sx + x * xdim) / 0x10000, (sy + y * ydim) / 0x10000,
798 							xscale, yscale, m_drawmode_table);
799 			}
800 		}
801 #ifdef MAME_DEBUG
802 #if 0
803 if (machine().input().code_pressed(KEYCODE_X))
804 {   /* Display some info on each sprite */
805 	sprintf(buf, "%04x",attr);
806 	ui_draw_text(buf, sx>>16, sy>>16);
807 }
808 #endif
809 #endif
810 	}   /* end sprite loop */
811 }
812 
813 
814 /***************************************************************************
815 
816 
817                                 Screen Drawing
818 
819 
820 ***************************************************************************/
821 
822 #ifdef MAME_DEBUG
823 #define CISCHEAT_LAYERSCTRL \
824 m_debugsprites = 0; \
825 if ( machine().input().code_pressed(KEYCODE_Z) || machine().input().code_pressed(KEYCODE_X) ) \
826 { \
827 	int msk = 0; \
828 	if (machine().input().code_pressed(KEYCODE_Q))  { msk |= 0x01;} \
829 	if (machine().input().code_pressed(KEYCODE_W))  { msk |= 0x02;} \
830 	if (machine().input().code_pressed(KEYCODE_E))  { msk |= 0x04;} \
831 	if (machine().input().code_pressed(KEYCODE_A))  { msk |= 0x08; m_debugsprites = 1;} \
832 	if (machine().input().code_pressed(KEYCODE_S))  { msk |= 0x08; m_debugsprites = 2;} \
833 	if (machine().input().code_pressed(KEYCODE_D))  { msk |= 0x08; m_debugsprites = 3;} \
834 	if (machine().input().code_pressed(KEYCODE_F))  { msk |= 0x08; m_debugsprites = 4;} \
835 	if (machine().input().code_pressed(KEYCODE_R))  { msk |= 0x10;} \
836 	if (machine().input().code_pressed(KEYCODE_T))  { msk |= 0x20;} \
837 	\
838 	if (msk != 0) active_layers1 &= msk; \
839 } \
840 \
841 { \
842 	if ( machine().input().code_pressed(KEYCODE_Z) && machine().input().code_pressed_once(KEYCODE_U) ) \
843 		m_show_unknown ^= 1; \
844 }
845 #else
846 #define CISCHEAT_LAYERSCTL
847 #endif
848 
849 /**************************************************************************
850                                 Big Run
851 **************************************************************************/
852 
screen_update_bigrun(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)853 uint32_t cischeat_state::screen_update_bigrun(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
854 {
855 	int i;
856 
857 	bitmap.fill(0x1000, cliprect);
858 
859 	for (i = 7; i >= 4; i--)
860 	{
861 		/* bitmap, cliprect, road, min_priority, max_priority, transparency */
862 		cischeat_draw_road(bitmap,cliprect,0,i,i,(i != 7));
863 		cischeat_draw_road(bitmap,cliprect,1,i,i,true);
864 		bigrun_draw_sprites(bitmap,cliprect,i+1,i);
865 	}
866 
867 	m_tmap[0]->draw(screen, bitmap, cliprect, 0, 0 );
868 	m_tmap[1]->draw(screen, bitmap, cliprect, 0, 0 );
869 
870 	for (i = 3; i >= 0; i--)
871 	{
872 		/* bitmap, cliprect, road, min_priority, max_priority, transparency */
873 		cischeat_draw_road(bitmap,cliprect,0,i,i,true);
874 		cischeat_draw_road(bitmap,cliprect,1,i,i,true);
875 		bigrun_draw_sprites(bitmap,cliprect,i+1,i);
876 	}
877 
878 	m_tmap[2]->draw(screen, bitmap, cliprect, 0, 0 );
879 
880 	return 0;
881 }
882 
883 
884 /**************************************************************************
885                                 Cisco Heat
886 **************************************************************************/
887 
screen_update_cischeat(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)888 uint32_t cischeat_state::screen_update_cischeat(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
889 {
890 	int active_layers1, flag;
891 
892 #ifdef MAME_DEBUG
893 	/* FAKE Videoreg */
894 	active_layers1 = m_active_layers;
895 	if (active_layers1 == 0)   active_layers1 = 0x3f;
896 #else
897 	active_layers1 = 0x3f;
898 #endif
899 
900 #ifdef MAME_DEBUG
901 	CISCHEAT_LAYERSCTRL
902 #endif
903 
904 	bitmap.fill(0, cliprect);
905 
906 										/* bitmap, road, priority, transparency */
907 	if (active_layers1 & 0x10) cischeat_draw_road(bitmap,cliprect,0,7,5,false);
908 	if (active_layers1 & 0x20) cischeat_draw_road(bitmap,cliprect,1,7,5,true);
909 
910 	flag = 0;
911 	cischeat_tmap_DRAW(0)
912 //  else bitmap.fill(0, cliprect);
913 	cischeat_tmap_DRAW(1)
914 
915 	if (active_layers1 & 0x08) cischeat_draw_sprites(bitmap,cliprect,15,3);
916 	if (active_layers1 & 0x10) cischeat_draw_road(bitmap,cliprect,0,4,1,true);
917 	if (active_layers1 & 0x20) cischeat_draw_road(bitmap,cliprect,1,4,1,true);
918 	if (active_layers1 & 0x08) cischeat_draw_sprites(bitmap,cliprect,2,2);
919 	if (active_layers1 & 0x10) cischeat_draw_road(bitmap,cliprect,0,0,0,true);
920 	if (active_layers1 & 0x20) cischeat_draw_road(bitmap,cliprect,1,0,0,true);
921 	if (active_layers1 & 0x08) cischeat_draw_sprites(bitmap,cliprect,1,0);
922 	cischeat_tmap_DRAW(2)
923 
924 	/* for the map screen */
925 	if (active_layers1 & 0x08) cischeat_draw_sprites(bitmap,cliprect,0+16,0+16);
926 
927 	return 0;
928 }
929 
930 
931 
932 /**************************************************************************
933                             F1 GrandPrix Star
934 **************************************************************************/
935 
screen_update_f1gpstar(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)936 uint32_t cischeat_state::screen_update_f1gpstar(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
937 {
938 	int active_layers1, flag;
939 
940 #ifdef MAME_DEBUG
941 	/* FAKE Videoreg */
942 	active_layers1 = m_active_layers;
943 	if (active_layers1 == 0)   active_layers1 = 0x3f;
944 #else
945 	active_layers1 = 0x3f;
946 #endif
947 
948 #ifdef MAME_DEBUG
949 	CISCHEAT_LAYERSCTRL
950 #endif
951 
952 	bitmap.fill(0, cliprect);
953 
954 /*  1: clouds 5, grad 7, road 0     2: clouds 5, grad 7, road 0, tunnel roof 0 */
955 
956 	/* road 1!! 0!! */                  /* bitmap, road, min_priority, max_priority, transparency */
957 	if (active_layers1 & 0x20) f1gpstar_draw_road(bitmap,cliprect,1,6,7,false);
958 	if (active_layers1 & 0x10) f1gpstar_draw_road(bitmap,cliprect,0,6,7,true);
959 
960 	flag = 0;
961 	cischeat_tmap_DRAW(0)
962 //  else bitmap.fill(0, cliprect);
963 	cischeat_tmap_DRAW(1)
964 
965 	/* road 1!! 0!! */                  /* bitmap, road, min_priority, max_priority, transparency */
966 	if (active_layers1 & 0x20) f1gpstar_draw_road(bitmap,cliprect,1,1,5,true);
967 	if (active_layers1 & 0x10) f1gpstar_draw_road(bitmap,cliprect,0,1,5,true);
968 
969 	if (active_layers1 & 0x08) cischeat_draw_sprites(bitmap,cliprect,15,2);
970 
971 	/* road 1!! 0!! */                  /* bitmap, road, min_priority, max_priority, transparency */
972 	if (active_layers1 & 0x20) f1gpstar_draw_road(bitmap,cliprect,1,0,0,true);
973 	if (active_layers1 & 0x10) f1gpstar_draw_road(bitmap,cliprect,0,0,0,true);
974 
975 	if (active_layers1 & 0x08) cischeat_draw_sprites(bitmap,cliprect,1,1);
976 	cischeat_tmap_DRAW(2)
977 	if (active_layers1 & 0x08) cischeat_draw_sprites(bitmap,cliprect,0,0);
978 
979 	return 0;
980 }
981 
982 
983 
984 /**************************************************************************
985                                 Scud Hammer
986 **************************************************************************/
987 
screen_update_scudhamm(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)988 uint32_t cischeat_state::screen_update_scudhamm(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
989 {
990 	int active_layers1 = 0x0d;
991 
992 #ifdef MAME_DEBUG
993 m_debugsprites = 0;
994 if ( machine().input().code_pressed(KEYCODE_Z) || machine().input().code_pressed(KEYCODE_X) )
995 {
996 #if 1
997 	{
998 		popmessage("Cmd: %04X Pos:%04X Lim:%04X Inp:%02X",
999 							m_scudhamm_motor_command,
1000 							scudhamm_motor_pos_r(),
1001 							scudhamm_motor_status_r(),
1002 							scudhamm_analog_r() );
1003 
1004 #if 0
1005 	// captflag
1006 	{
1007 		popmessage( "[%04x] [%04x]\nLEDS %04x", m_captflag_motor_command[LEFT], m_captflag_motor_command[RIGHT], m_captflag_leds );
1008 		m_captflag_motor_command[LEFT] = m_captflag_motor_command[RIGHT] = 0;
1009 	}
1010 #endif
1011 
1012 	}
1013 #endif
1014 
1015 }
1016 #endif
1017 
1018 	bitmap.fill(0, cliprect);
1019 
1020 	if (active_layers1 & 0x01) m_tmap[0]->draw(screen, bitmap, cliprect, 0, 0);
1021 	// no layer 1
1022 	if (active_layers1 & 0x08) cischeat_draw_sprites(bitmap,cliprect,0,15);
1023 	if (active_layers1 & 0x04) m_tmap[2]->draw(screen, bitmap, cliprect, 0, 0);
1024 
1025 	return 0;
1026 }
1027