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