1 /***************************************************************************
2
3 Caveman Ninja Video emulation - Bryan McPhail, mish@tendril.co.uk
4
5 ****************************************************************************/
6
7 #include "driver.h"
8 #include "vidhrdw/generic.h"
9 #include "deco16ic.h"
10
11 /******************************************************************************/
12
cninja_bank_callback(const int bank)13 static int cninja_bank_callback(const int bank)
14 {
15 if ((bank>>4)&0xf) return 0x0000; /* Only 2 banks */
16 return 0x1000;
17 }
18
edrandy_bank_callback(const int bank)19 static int edrandy_bank_callback(const int bank)
20 {
21 if ((bank>>4)&0xf) return 0x0000; /* Only 2 banks */
22 return 0x1000;
23 }
24
robocop2_bank_callback(const int bank)25 static int robocop2_bank_callback(const int bank)
26 {
27 return (bank&0x30)<<8;
28 }
29
mutantf_1_bank_callback(const int bank)30 static int mutantf_1_bank_callback(const int bank)
31 {
32 return ((bank>>4)&0x3)<<12;
33 }
34
mutantf_2_bank_callback(const int bank)35 static int mutantf_2_bank_callback(const int bank)
36 {
37 return ((bank>>5)&0x1)<<14;
38 }
39
40 /******************************************************************************/
41
VIDEO_START(cninja)42 VIDEO_START( cninja )
43 {
44 if (deco16_2_video_init(1))
45 return 1;
46
47 deco16_set_tilemap_bank_callback(2,cninja_bank_callback);
48 deco16_set_tilemap_bank_callback(3,cninja_bank_callback);
49 deco16_set_tilemap_colour_base(3,48);
50
51 return 0;
52 }
53
VIDEO_START(stoneage)54 VIDEO_START( stoneage )
55 {
56 if (deco16_2_video_init(1))
57 return 1;
58
59 deco16_set_tilemap_bank_callback(2,edrandy_bank_callback);
60 deco16_set_tilemap_bank_callback(3,edrandy_bank_callback);
61 deco16_set_tilemap_colour_base(3,48);
62
63 /* The bootleg has broken scroll registers */
64 tilemap_set_scrolldx(deco16_get_tilemap(3,0),-10,-10);
65 tilemap_set_scrolldx(deco16_get_tilemap(1,0),-10,-10);
66 tilemap_set_scrolldx(deco16_get_tilemap(0,1),2,2);
67
68 return 0;
69 }
70
VIDEO_START(edrandy)71 VIDEO_START( edrandy )
72 {
73 if (deco16_2_video_init(0))
74 return 1;
75
76 deco16_set_tilemap_bank_callback(2,edrandy_bank_callback);
77 deco16_set_tilemap_bank_callback(3,edrandy_bank_callback);
78 deco16_set_tilemap_colour_base(3,48);
79
80 return 0;
81 }
82
VIDEO_START(robocop2)83 VIDEO_START( robocop2 )
84 {
85 if (deco16_2_video_init(0))
86 return 1;
87
88 deco16_set_tilemap_bank_callback(1,robocop2_bank_callback);
89 deco16_set_tilemap_bank_callback(2,robocop2_bank_callback);
90 deco16_set_tilemap_bank_callback(3,robocop2_bank_callback);
91 deco16_set_tilemap_colour_base(3,48);
92
93 return 0;
94 }
95
VIDEO_START(mutantf)96 VIDEO_START( mutantf )
97 {
98 if (deco16_2_video_init(0))
99 return 1;
100
101 deco16_set_tilemap_bank_callback(0,mutantf_1_bank_callback);
102 deco16_set_tilemap_bank_callback(1,mutantf_2_bank_callback);
103 deco16_set_tilemap_bank_callback(2,mutantf_1_bank_callback);
104 deco16_set_tilemap_bank_callback(3,mutantf_1_bank_callback);
105
106 deco16_set_tilemap_colour_base(1,0x30);
107 deco16_set_tilemap_colour_base(2,0x20);
108 deco16_set_tilemap_colour_base(3,0x40);
109
110 alpha_set_level(0x80);
111
112 return 0;
113 }
114
115 /******************************************************************************/
116
VIDEO_EOF(cninja)117 VIDEO_EOF( cninja )
118 {
119 deco16_raster_display_position=0;
120 }
121
raster_pf3_draw(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int flags,int pri)122 static void raster_pf3_draw(struct mame_bitmap *bitmap, const struct rectangle *cliprect, int flags, int pri)
123 {
124 struct tilemap *tilemap=deco16_get_tilemap(2,0);
125 int ptr=0,start,end=0;
126 struct rectangle clip;
127 int overflow=deco16_raster_display_position;
128
129 clip.min_x = cliprect->min_x;
130 clip.max_x = cliprect->max_x;
131
132 /* Finish list up to end of visible display */
133 deco16_raster_display_list[overflow++]=255;
134 deco16_raster_display_list[overflow++]=deco16_pf12_control[1];
135 deco16_raster_display_list[overflow++]=deco16_pf12_control[2];
136 deco16_raster_display_list[overflow++]=deco16_pf12_control[3];
137 deco16_raster_display_list[overflow++]=deco16_pf12_control[4];
138 deco16_raster_display_list[overflow++]=deco16_pf34_control[1];
139 deco16_raster_display_list[overflow++]=deco16_pf34_control[2];
140 deco16_raster_display_list[overflow++]=deco16_pf34_control[3];
141 deco16_raster_display_list[overflow++]=deco16_pf34_control[4];
142
143 while (ptr<overflow) {
144 start=end;
145 end=deco16_raster_display_list[ptr++];
146
147 /* Restore state of registers before IRQ */
148 deco16_pf12_control[1]=deco16_raster_display_list[ptr++];
149 deco16_pf12_control[2]=deco16_raster_display_list[ptr++];
150 deco16_pf12_control[3]=deco16_raster_display_list[ptr++];
151 deco16_pf12_control[4]=deco16_raster_display_list[ptr++];
152 deco16_pf34_control[1]=deco16_raster_display_list[ptr++];
153 deco16_pf34_control[2]=deco16_raster_display_list[ptr++];
154 deco16_pf34_control[3]=deco16_raster_display_list[ptr++];
155 deco16_pf34_control[4]=deco16_raster_display_list[ptr++];
156
157 clip.min_y = start;
158 clip.max_y = end;
159
160 /* Update tilemap for this register state, and draw */
161 deco16_pf34_update(deco16_pf3_rowscroll,deco16_pf4_rowscroll);
162 tilemap_draw(bitmap,&clip,tilemap,flags,pri);
163 }
164 }
165
166 /******************************************************************************/
167
cninja_drawsprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect)168 static void cninja_drawsprites(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
169 {
170 int offs;
171
172 for (offs = 0x400-4;offs >=0 ;offs -= 4)
173 {
174 int x,y,sprite,colour,multi,fx,fy,inc,flash,mult,pri=0;
175
176 sprite = buffered_spriteram16[offs+1];
177 if (!sprite) continue;
178
179 x = buffered_spriteram16[offs+2];
180
181 /* Sprite/playfield priority */
182 switch (x&0xc000) {
183 case 0x0000: pri=0; break;
184 case 0x4000: pri=0xf0; break;
185 case 0x8000: pri=0xf0|0xcc; break;
186 case 0xc000: pri=0xf0|0xcc; break; /* Perhaps 0xf0|0xcc|0xaa (Sprite under bottom layer) */
187 }
188
189 y = buffered_spriteram16[offs];
190 flash=y&0x1000;
191 if (flash && (cpu_getcurrentframe() & 1)) continue;
192 colour = (x >> 9) &0x1f;
193
194 fx = y & 0x2000;
195 fy = y & 0x4000;
196 multi = (1 << ((y & 0x0600) >> 9)) - 1; /* 1x, 2x, 4x, 8x height */
197
198 x = x & 0x01ff;
199 y = y & 0x01ff;
200 if (x >= 256) x -= 512;
201 if (y >= 256) y -= 512;
202 x = 240 - x;
203 y = 240 - y;
204
205 sprite &= ~multi;
206 if (fy)
207 inc = -1;
208 else
209 {
210 sprite += multi;
211 inc = 1;
212 }
213
214 if (flip_screen) {
215 y=240-y;
216 x=240-x;
217 if (fx) fx=0; else fx=1;
218 if (fy) fy=0; else fy=1;
219 mult=16;
220 }
221 else mult=-16;
222
223 while (multi >= 0)
224 {
225 pdrawgfx(bitmap,Machine->gfx[3],
226 sprite - multi * inc,
227 colour,
228 fx,fy,
229 x,y + mult * multi,
230 cliprect,TRANSPARENCY_PEN,0,pri);
231
232 multi--;
233 }
234 }
235 }
236
robocop2_drawsprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect)237 static void robocop2_drawsprites(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
238 {
239 int offs;
240
241 for (offs = 0x400-4;offs >=0 ;offs -= 4)
242 {
243 int x,y,sprite,colour,multi,fx,fy,inc,flash,mult,pri=0;
244 sprite = buffered_spriteram16[offs+1];
245 if (!sprite) continue;
246
247 x = buffered_spriteram16[offs+2];
248
249 /* Sprite/playfield priority */
250 switch (x&0xc000) {
251 case 0x0000: pri=0; break;
252 case 0x4000: pri=0xf0; break;
253 case 0x8000: pri=0xf0|0xcc; break;
254 case 0xc000: pri=0xf0|0xcc; break; /* Perhaps 0xf0|0xcc|0xaa (Sprite under bottom layer) */
255 }
256
257 y = buffered_spriteram16[offs];
258 flash=y&0x1000;
259 if (flash && (cpu_getcurrentframe() & 1)) continue;
260 colour = (x >> 9) &0x1f;
261
262 fx = y & 0x2000;
263 fy = y & 0x4000;
264 multi = (1 << ((y & 0x0600) >> 9)) - 1; /* 1x, 2x, 4x, 8x height */
265
266 x = x & 0x01ff;
267 y = y & 0x01ff;
268 if (x >= 320) x -= 512;
269 if (y >= 256) y -= 512;
270 x = 304 - x;
271 y = 240 - y;
272
273 sprite &= ~multi;
274 if (fy)
275 inc = -1;
276 else
277 {
278 sprite += multi;
279 inc = 1;
280 }
281
282 if (flip_screen) {
283 y=240-y;
284 x=304-x;
285 if (fx) fx=0; else fx=1;
286 if (fy) fy=0; else fy=1;
287 mult=16;
288 }
289 else mult=-16;
290
291 while (multi >= 0)
292 {
293 pdrawgfx(bitmap,Machine->gfx[3],
294 sprite - multi * inc,
295 colour,
296 fx,fy,
297 x,y + mult * multi,
298 cliprect,TRANSPARENCY_PEN,0,pri);
299
300 multi--;
301 }
302 }
303 }
304
mutantf_drawsprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect,const data16_t * spriteptr,int gfxbank)305 static void mutantf_drawsprites(struct mame_bitmap *bitmap, const struct rectangle *cliprect, const data16_t *spriteptr, int gfxbank)
306 {
307 int offs,end,inc;
308
309 /*
310 Alternate format from most 16 bit games - same as Captain America
311
312 Word 0:
313 0x8000: Y flip
314 0x4000: X flip
315 0x2000: Flash (Sprite toggles on/off every frame)
316 0x1fff: Y value
317 Word 1:
318 0xffff: X value
319 Word 2:
320 0xf000: Block height
321 0x0f00: Block width
322 0x00e0: Unused?
323 0x001f: Colour
324 Word 3:
325 0xffff: Sprite value
326 */
327
328 /* This may look strange, but the alpha-blended sprite chip definitely draws end to
329 front, ie, reversed from normal pdrawgfx style. */
330 if (gfxbank==4) {
331 offs=0;
332 end=0x400;
333 inc=4;
334 } else {
335 offs=0x3fc;
336 end=-4;
337 inc=-4;
338 }
339
340 while (offs!=end)
341 {
342 int x,y,sprite,colour,fx,fy,w,h,sx,sy,x_mult,y_mult;
343 int trans=TRANSPARENCY_PEN;
344
345 sprite = spriteptr[offs+3];
346 if (!sprite) {
347 offs+=inc;
348 continue;
349 }
350
351 sx = spriteptr[offs+1];
352
353 h = (spriteptr[offs+2]&0xf000)>>12;
354 w = (spriteptr[offs+2]&0x0f00)>> 8;
355
356 sy = spriteptr[offs];
357 if ((sy&0x2000) && (cpu_getcurrentframe() & 1)) {
358 offs+=inc;
359 continue;
360 }
361
362 colour = (spriteptr[offs+2] >>0) & 0x1f;
363
364 if (gfxbank==4) { /* Seems to be always alpha'd */
365 trans=TRANSPARENCY_ALPHA;
366 colour&=0xf;
367 }
368
369 fx = (spriteptr[offs+0]&0x4000);
370 fy = (spriteptr[offs+0]&0x8000);
371
372 if (flip_screen) {
373 if (fx) fx=0; else fx=1;
374 if (fy) fy=0; else fy=1;
375
376 sx = sx & 0x01ff;
377 sy = sy & 0x01ff;
378 if (sx>0x180) sx=-(0x200 - sx);
379 if (sy>0x180) sy=-(0x200 - sy);
380
381 if (fx) { x_mult=-16; sx+=16*w; } else { x_mult=16; sx-=16; }
382 if (fy) { y_mult=-16; sy+=16*h; } else { y_mult=16; sy-=16; }
383 } else {
384 sx = sx & 0x01ff;
385 sy = sy & 0x01ff;
386 if (sx&0x100) sx=-(0x100 - (sx&0xff));
387 if (sy&0x100) sy=-(0x100 - (sy&0xff));
388 sx = 304 - sx;
389 sy = 240 - sy;
390 if (sx >= 432) sx -= 512;
391 if (sy >= 384) sy -= 512;
392 if (fx) { x_mult=-16; sx+=16; } else { x_mult=16; sx-=16*w; }
393 if (fy) { y_mult=-16; sy+=16; } else { y_mult=16; sy-=16*h; }
394 }
395
396 for (x=0; x<w; x++) {
397 for (y=0; y<h; y++) {
398 pdrawgfx(bitmap,Machine->gfx[gfxbank],
399 sprite + y + h * x,
400 colour,
401 fx,fy,
402 sx + x_mult * (w-x),sy + y_mult * (h-y),
403 &Machine->visible_area,trans,0,0);
404 }
405 }
406
407 offs+=inc;
408 }
409 }
410
411 /******************************************************************************/
412
VIDEO_UPDATE(cninja)413 VIDEO_UPDATE( cninja )
414 {
415 flip_screen_set( deco16_pf12_control[0]&0x80 );
416 deco16_pf12_update(deco16_pf1_rowscroll,deco16_pf2_rowscroll);
417 deco16_pf34_update(deco16_pf3_rowscroll,deco16_pf4_rowscroll);
418
419 /* Draw playfields */
420 fillbitmap(priority_bitmap,0,cliprect);
421 fillbitmap(bitmap,Machine->pens[512],cliprect);
422 deco16_tilemap_4_draw(bitmap,cliprect,TILEMAP_IGNORE_TRANSPARENCY,1);
423 deco16_tilemap_3_draw(bitmap,cliprect,0,2);
424 deco16_tilemap_2_draw(bitmap,cliprect,TILEMAP_BACK,2);
425 deco16_tilemap_2_draw(bitmap,cliprect,TILEMAP_FRONT,4);
426 cninja_drawsprites(bitmap,cliprect);
427 deco16_tilemap_1_draw(bitmap,cliprect,0,0);
428 }
429
VIDEO_UPDATE(edrandy)430 VIDEO_UPDATE( edrandy )
431 {
432 flip_screen_set( deco16_pf12_control[0]&0x80 );
433 deco16_pf12_update(deco16_pf1_rowscroll,deco16_pf2_rowscroll);
434 deco16_pf34_update(deco16_pf3_rowscroll,deco16_pf4_rowscroll);
435
436 fillbitmap(priority_bitmap,0,cliprect);
437 fillbitmap(bitmap,Machine->pens[0],&Machine->visible_area);
438 deco16_tilemap_4_draw(bitmap,cliprect,TILEMAP_IGNORE_TRANSPARENCY,1);
439 if (deco16_raster_display_position)
440 raster_pf3_draw(bitmap,cliprect,0,2);
441 else
442 deco16_tilemap_3_draw(bitmap,cliprect,0,2);
443 deco16_tilemap_2_draw(bitmap,cliprect,0,4);
444 cninja_drawsprites(bitmap,cliprect);
445 deco16_tilemap_1_draw(bitmap,cliprect,0,0);
446 }
447
VIDEO_UPDATE(robocop2)448 VIDEO_UPDATE( robocop2 )
449 {
450 /* One of the tilemap chips can switch between 2 tilemaps at 4bpp, or 1 at 8bpp */
451 if (deco16_priority&4) {
452 deco16_set_tilemap_colour_mask(2,0);
453 deco16_set_tilemap_colour_mask(3,0);
454 deco16_pf34_set_gfxbank(0,4);
455 } else {
456 deco16_set_tilemap_colour_mask(2,0xf);
457 deco16_set_tilemap_colour_mask(3,0xf);
458 deco16_pf34_set_gfxbank(0,2);
459 }
460
461 /* Update playfields */
462 flip_screen_set( deco16_pf12_control[0]&0x80 );
463 deco16_pf12_update(deco16_pf1_rowscroll,deco16_pf2_rowscroll);
464 deco16_pf34_update(deco16_pf3_rowscroll,deco16_pf4_rowscroll);
465
466 /* Draw playfields */
467 fillbitmap(priority_bitmap,0,cliprect);
468 fillbitmap(bitmap,Machine->pens[0x200],cliprect);
469 if ((deco16_priority&4)==0)
470 deco16_tilemap_4_draw(bitmap,cliprect,TILEMAP_IGNORE_TRANSPARENCY,1);
471
472 /* Switchable priority */
473 switch (deco16_priority&0x8) {
474 case 8:
475 deco16_tilemap_2_draw(bitmap,cliprect,0,2);
476 if (deco16_raster_display_position)
477 raster_pf3_draw(bitmap,cliprect,0,4);
478 else
479 deco16_tilemap_3_draw(bitmap,cliprect,0,4);
480 break;
481 default:
482 case 0:
483 if (deco16_raster_display_position)
484 raster_pf3_draw(bitmap,cliprect,0,2);
485 else
486 deco16_tilemap_3_draw(bitmap,cliprect,0,2);
487 deco16_tilemap_2_draw(bitmap,cliprect,0,4);
488 break;
489 }
490
491 robocop2_drawsprites(bitmap,cliprect);
492 deco16_tilemap_1_draw(bitmap,cliprect,0,0);
493 }
494
VIDEO_UPDATE(mutantf)495 VIDEO_UPDATE( mutantf )
496 {
497 flip_screen_set( deco16_pf12_control[0]&0x80 );
498 deco16_pf12_update(deco16_pf1_rowscroll,deco16_pf2_rowscroll);
499 deco16_pf34_update(deco16_pf3_rowscroll,deco16_pf4_rowscroll);
500
501 /* Draw playfields */
502 fillbitmap(bitmap,Machine->pens[0x400],cliprect); /* Confirmed */
503
504 /* There is no priority prom on this board, but there is a
505 priority control word, the only values used in game appear
506 to be 2, 6 & 7 though:
507
508 Bit 0: If set sprite chip 2 above sprite chip 1 else vice versa
509 Bit 1: Always set?
510 Bit 2: Almost always set (Sometimes not set on screen transitions)
511
512 The other bits may control alpha blend on the 2nd sprite chip, or
513 layer order.
514 */
515 deco16_tilemap_4_draw(bitmap,cliprect,TILEMAP_IGNORE_TRANSPARENCY,0);
516 deco16_tilemap_2_draw(bitmap,cliprect,0,0);
517 deco16_tilemap_3_draw(bitmap,cliprect,0,0);
518
519 /* We need to abuse the priority bitmap a little by clearing it before
520 drawing each sprite layer. This is because there is no priority
521 orthogonality between sprite layers, but the alpha layer must obey
522 priority between sprites in each layer. Ie, if we didn't do this,
523 then when two alpha blended shadows overlapped then they would be 25%
524 transparent against the background, rather than 50% */
525 if (deco16_priority&1) {
526 fillbitmap(priority_bitmap,0,cliprect);
527 mutantf_drawsprites(bitmap,cliprect,buffered_spriteram16,3);
528 fillbitmap(priority_bitmap,0,cliprect);
529 mutantf_drawsprites(bitmap,cliprect,buffered_spriteram16_2,4);
530 } else {
531 fillbitmap(priority_bitmap,0,cliprect);
532 mutantf_drawsprites(bitmap,cliprect,buffered_spriteram16_2,4);
533 fillbitmap(priority_bitmap,0,cliprect);
534 mutantf_drawsprites(bitmap,cliprect,buffered_spriteram16,3);
535 }
536 deco16_tilemap_1_draw(bitmap,cliprect,0,0);
537 }
538