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