1 #include "driver.h"
2 #include "vidhrdw/generic.h"
3 
4 
5 data8_t *mappy_videoram;
6 data8_t *mappy_spriteram;
7 
8 static data8_t mappy_scroll;
9 static struct tilemap *bg_tilemap;
10 
11 static struct mame_bitmap *sprite_bitmap;
12 
13 
14 /***************************************************************************
15 
16   Convert the color PROMs.
17 
18   All games except Phozon have one 32x8 palette PROM and two 256x4 color
19   lookup table PROMs (one for characters, one for sprites), except todruaga
20   which has a larger 1024x4 PROM for sprites.
21   The palette PROM is connected to the RGB output this way:
22 
23   bit 7 -- 220 ohm resistor  -- BLUE
24         -- 470 ohm resistor  -- BLUE
25         -- 220 ohm resistor  -- GREEN
26         -- 470 ohm resistor  -- GREEN
27         -- 1  kohm resistor  -- GREEN
28         -- 220 ohm resistor  -- RED
29         -- 470 ohm resistor  -- RED
30   bit 0 -- 1  kohm resistor  -- RED
31 
32   The way how the lookup tables are mapped to palette colors, and priority
33   handling, are controlled by a PAL (SPV-5 in Super Pacman, MPI-4 in Mappy),
34   so the two hardwares work differently.
35   Super Pacman has a special "super priority" for sprite colors, allowing
36   one pen to be over high priority tiles (used by Pac & Pal for ghost eyes),
37   which isn't present in Mappy.
38 
39 ***************************************************************************/
40 
PALETTE_INIT(superpac)41 PALETTE_INIT( superpac )
42 {
43 	int i;
44 
45 	for (i = 0;i < Machine->drv->total_colors;i++)
46 	{
47 		int bit0,bit1,bit2,r,g,b;
48 
49 		bit0 = (*color_prom >> 0) & 0x01;
50 		bit1 = (*color_prom >> 1) & 0x01;
51 		bit2 = (*color_prom >> 2) & 0x01;
52 		r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
53 		bit0 = (*color_prom >> 3) & 0x01;
54 		bit1 = (*color_prom >> 4) & 0x01;
55 		bit2 = (*color_prom >> 5) & 0x01;
56 		g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
57 		bit0 = 0;
58 		bit1 = (*color_prom >> 6) & 0x01;
59 		bit2 = (*color_prom >> 7) & 0x01;
60 		b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
61 
62 		palette_set_color(i,r,g,b);
63 		color_prom++;
64 	}
65 
66 	/* characters */
67 	for (i = 0; i < 64*4; i++)
68 		colortable[i] = (color_prom[i] & 0x0f) ^ 0x1f;
69 
70 	/* sprites */
71 	for (i = 64*4; i < 128*4; i++)
72 		colortable[i] = color_prom[i] & 0x0f;
73 }
74 
PALETTE_INIT(mappy)75 PALETTE_INIT( mappy )
76 {
77 	int i;
78 
79 	for (i = 0;i < Machine->drv->total_colors;i++)
80 	{
81 		int bit0,bit1,bit2,r,g,b;
82 
83 		bit0 = (*color_prom >> 0) & 0x01;
84 		bit1 = (*color_prom >> 1) & 0x01;
85 		bit2 = (*color_prom >> 2) & 0x01;
86 		r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
87 		bit0 = (*color_prom >> 3) & 0x01;
88 		bit1 = (*color_prom >> 4) & 0x01;
89 		bit2 = (*color_prom >> 5) & 0x01;
90 		g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
91 		bit0 = 0;
92 		bit1 = (*color_prom >> 6) & 0x01;
93 		bit2 = (*color_prom >> 7) & 0x01;
94 		b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
95 
96 		palette_set_color(i,r,g,b);
97 		color_prom++;
98 	}
99 
100 	/* characters */
101 	for (i = 0*4;i < 64*4;i++)
102 		colortable[i] = (color_prom[i^3] & 0x0f) + 0x10;
103 
104 	/* sprites */
105 	for (i = 64*4;i < Machine->drv->color_table_len;i++)
106 		colortable[i] = color_prom[i] & 0x0f;
107 }
108 
109 
110 /***************************************************************************
111 
112   In Phozon, the palette PROMs are connected to the RGB output this way:
113 
114   bit 3 -- 220 ohm resistor  -- RED/GREEN/BLUE
115         -- 470 ohm resistor  -- RED/GREEN/BLUE
116         -- 1  kohm resistor  -- RED/GREEN/BLUE
117   bit 0 -- 2.2kohm resistor  -- RED/GREEN/BLUE
118 
119 ***************************************************************************/
120 
PALETTE_INIT(phozon)121 PALETTE_INIT( phozon )
122 {
123 	int i;
124 	#define TOTAL_COLORS(gfxn) (Machine->gfx[gfxn]->total_colors * Machine->gfx[gfxn]->color_granularity)
125 	#define COLOR(gfxn,offs) (colortable[Machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs])
126 
127 	for (i = 0; i < Machine->drv->total_colors; i++){
128 		int bit0,bit1,bit2,bit3,r,g,b;
129 
130 		/* red component */
131 		bit0 = (color_prom[i] >> 0) & 0x01;
132 		bit1 = (color_prom[i] >> 1) & 0x01;
133 		bit2 = (color_prom[i] >> 2) & 0x01;
134 		bit3 = (color_prom[i] >> 3) & 0x01;
135 		r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
136 		/* green component */
137 		bit0 = (color_prom[i + 0x100] >> 0) & 0x01;
138 		bit1 = (color_prom[i + 0x100] >> 1) & 0x01;
139 		bit2 = (color_prom[i + 0x100] >> 2) & 0x01;
140 		bit3 = (color_prom[i + 0x100] >> 3) & 0x01;
141 		g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
142 		/* blue component */
143 		bit0 = (color_prom[i + 0x200] >> 0) & 0x01;
144 		bit1 = (color_prom[i + 0x200] >> 1) & 0x01;
145 		bit2 = (color_prom[i + 0x200] >> 2) & 0x01;
146 		bit3 = (color_prom[i + 0x200] >> 3) & 0x01;
147 		b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
148 
149 		palette_set_color(i,r,g,b);
150 	}
151 
152 	color_prom += 0x300;
153 	/* color_prom now points to the beginning of the lookup table */
154 
155 	/* characters */
156 	for (i = 0; i < TOTAL_COLORS(0); i++)
157 		COLOR(0,i) = (*(color_prom++) & 0x0f);
158 	/* sprites */
159 	for (i = 0; i < TOTAL_COLORS(1); i++)
160 		COLOR(1,i) = (*(color_prom++) & 0x0f) + 0x10;
161 }
162 
163 
164 
165 /***************************************************************************
166 
167   Callbacks for the TileMap code
168 
169 ***************************************************************************/
170 
171 /* convert from 32x32 to 36x28 */
superpac_tilemap_scan(UINT32 col,UINT32 row,UINT32 num_cols,UINT32 num_rows)172 static UINT32 superpac_tilemap_scan(UINT32 col,UINT32 row,UINT32 num_cols,UINT32 num_rows)
173 {
174 	int offs;
175 
176 	row += 2;
177 	col -= 2;
178 	if (col & 0x20)
179 		offs = row + ((col & 0x1f) << 5);
180 	else
181 		offs = col + (row << 5);
182 
183 	return offs;
184 }
185 
186 /* tilemap is a composition of a 32x60 scrolling portion and two 2x28 fixed portions on the sides */
mappy_tilemap_scan(UINT32 col,UINT32 row,UINT32 num_cols,UINT32 num_rows)187 static UINT32 mappy_tilemap_scan(UINT32 col,UINT32 row,UINT32 num_cols,UINT32 num_rows)
188 {
189 	int offs;
190 
191 	col -= 2;
192 	if (col & 0x20)
193 	{
194 		/* in the following code, note the +2 followed by & 0x0f. This causes unintuitive
195 		   mapping from logical to hardware coordinates, which is true to the hardware.
196 		   Not doing it that way would cause missing tiles in motos and todruaga */
197 		if (row & 0x20)
198 			offs = 0x7ff;	// outside visible area
199 		else
200 			offs = ((row + 2) & 0x0f) + (row & 0x10) + ((col & 3) << 5) + 0x780;
201 	}
202 	else
203 		offs = col + (row << 5);
204 
205 	return offs;
206 }
207 
superpac_get_tile_info(int tile_index)208 static void superpac_get_tile_info(int tile_index)
209 {
210 	unsigned char attr = mappy_videoram[tile_index + 0x400];
211 	tile_info.priority = (attr & 0x40) >> 6;
212 	SET_TILE_INFO(
213 			0,
214 			mappy_videoram[tile_index],
215 			attr & 0x3f,
216 			0)
217 }
218 
phozon_get_tile_info(int tile_index)219 static void phozon_get_tile_info(int tile_index)
220 {
221 	unsigned char attr = mappy_videoram[tile_index + 0x400];
222 	tile_info.priority = (attr & 0x40) >> 6;
223 	SET_TILE_INFO(
224 			0,
225 			mappy_videoram[tile_index] + ((attr & 0x80) << 1),
226 			attr & 0x3f,
227 			0)
228 }
229 
mappy_get_tile_info(int tile_index)230 static void mappy_get_tile_info(int tile_index)
231 {
232 	unsigned char attr = mappy_videoram[tile_index + 0x800];
233 	tile_info.priority = (attr & 0x40) >> 6;
234 	SET_TILE_INFO(
235 			0,
236 			mappy_videoram[tile_index],
237 			attr & 0x3f,
238 			0)
239 }
240 
241 
242 
243 /***************************************************************************
244 
245   Start the video hardware emulation.
246 
247 ***************************************************************************/
248 
VIDEO_START(superpac)249 VIDEO_START( superpac )
250 {
251 	bg_tilemap = tilemap_create(superpac_get_tile_info,superpac_tilemap_scan,TILEMAP_TRANSPARENT_COLOR,8,8,36,28);
252 	sprite_bitmap = auto_bitmap_alloc(Machine->drv->screen_width,Machine->drv->screen_height);
253 
254 	if (!bg_tilemap || !sprite_bitmap)
255 		return 1;
256 
257 	tilemap_set_transparent_pen(bg_tilemap, 31);
258 
259 	spriteram = mappy_spriteram + 0x780;
260 	spriteram_2 = spriteram + 0x800;
261 	spriteram_3 = spriteram_2 + 0x800;
262 
263 	return 0;
264 }
265 
VIDEO_START(phozon)266 VIDEO_START( phozon )
267 {
268 	bg_tilemap = tilemap_create(phozon_get_tile_info,superpac_tilemap_scan,TILEMAP_TRANSPARENT_COLOR,8,8,36,28);
269 
270 	if (!bg_tilemap)
271 		return 1;
272 
273 	tilemap_set_transparent_pen(bg_tilemap, 15);
274 
275 	spriteram = mappy_spriteram + 0x780;
276 	spriteram_2 = spriteram + 0x800;
277 	spriteram_3 = spriteram_2 + 0x800;
278 
279 	return 0;
280 }
281 
VIDEO_START(mappy)282 VIDEO_START( mappy )
283 {
284 	bg_tilemap = tilemap_create(mappy_get_tile_info,mappy_tilemap_scan,TILEMAP_TRANSPARENT_COLOR,8,8,36,60);
285 
286 	if (!bg_tilemap)
287 		return 1;
288 
289 	tilemap_set_transparent_pen(bg_tilemap, 31);
290 	tilemap_set_scroll_cols(bg_tilemap, 36);
291 
292 	spriteram = mappy_spriteram + 0x780;
293 	spriteram_2 = spriteram + 0x800;
294 	spriteram_3 = spriteram_2 + 0x800;
295 
296 	return 0;
297 }
298 
299 
300 
301 /***************************************************************************
302 
303   Memory handlers
304 
305 ***************************************************************************/
306 
READ_HANDLER(superpac_videoram_r)307 READ_HANDLER( superpac_videoram_r )
308 {
309 	return mappy_videoram[offset];
310 }
311 
WRITE_HANDLER(superpac_videoram_w)312 WRITE_HANDLER( superpac_videoram_w )
313 {
314 	if (mappy_videoram[offset] != data)
315 	{
316 		mappy_videoram[offset] = data;
317 		tilemap_mark_tile_dirty(bg_tilemap,offset & 0x3ff);
318 	}
319 }
320 
READ_HANDLER(mappy_videoram_r)321 READ_HANDLER( mappy_videoram_r )
322 {
323 	return mappy_videoram[offset];
324 }
325 
WRITE_HANDLER(mappy_videoram_w)326 WRITE_HANDLER( mappy_videoram_w )
327 {
328 	if (mappy_videoram[offset] != data)
329 	{
330 		mappy_videoram[offset] = data;
331 		tilemap_mark_tile_dirty(bg_tilemap,offset & 0x7ff);
332 	}
333 }
334 
READ_HANDLER(mappy_spriteram_r)335 READ_HANDLER( mappy_spriteram_r )
336 {
337     return mappy_spriteram[offset];
338 }
339 
WRITE_HANDLER(mappy_spriteram_w)340 WRITE_HANDLER( mappy_spriteram_w )
341 {
342 	mappy_spriteram[offset] = data;
343 }
344 
WRITE_HANDLER(superpac_flipscreen_w)345 WRITE_HANDLER( superpac_flipscreen_w )
346 {
347 	flip_screen_set(data & 1);
348 }
349 
READ_HANDLER(superpac_flipscreen_r)350 READ_HANDLER( superpac_flipscreen_r )
351 {
352 	flip_screen_set(1);
353 	return 0xff;
354 }
355 
WRITE_HANDLER(mappy_scroll_w)356 WRITE_HANDLER( mappy_scroll_w )
357 {
358 	mappy_scroll = offset >> 3;
359 }
360 
361 
362 
363 /***************************************************************************
364 
365   Display refresh
366 
367 ***************************************************************************/
368 
369 /* also used by toypop.c */
mappy_draw_sprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int xoffs,int yoffs,int trans_color)370 void mappy_draw_sprites( struct mame_bitmap *bitmap, const struct rectangle *cliprect, int xoffs, int yoffs, int trans_color )
371 {
372 	int offs;
373 
374 	for (offs = 0;offs < 0x80;offs += 2)
375 	{
376 		/* is it on? */
377 		if ((spriteram_3[offs+1] & 2) == 0)
378 		{
379 			static int gfx_offs[2][2] =
380 			{
381 				{ 0, 1 },
382 				{ 2, 3 }
383 			};
384 			int sprite = spriteram[offs];
385 			int color = spriteram[offs+1];
386 			int sx = spriteram_2[offs+1] + 0x100 * (spriteram_3[offs+1] & 1) - 40 + xoffs;
387 			int sy = 256 - spriteram_2[offs] + yoffs + 1;	// sprites are buffered and delayed by one scanline
388 			int flipx = (spriteram_3[offs] & 0x01);
389 			int flipy = (spriteram_3[offs] & 0x02) >> 1;
390 			int sizex = (spriteram_3[offs] & 0x04) >> 2;
391 			int sizey = (spriteram_3[offs] & 0x08) >> 3;
392 			int x,y;
393 
394 			sprite &= ~sizex;
395 			sprite &= ~(sizey << 1);
396 
397 			if (flip_screen)
398 			{
399 				flipx ^= 1;
400 				flipy ^= 1;
401 			}
402 
403 			sy -= 16 * sizey;
404 			sy = (sy & 0xff) - 32;	// fix wraparound
405 
406 			for (y = 0;y <= sizey;y++)
407 			{
408 				for (x = 0;x <= sizex;x++)
409 				{
410 					drawgfx(bitmap,Machine->gfx[1],
411 						sprite + gfx_offs[y ^ (sizey * flipy)][x ^ (sizex * flipx)],
412 						color,
413 						flipx,flipy,
414 						sx + 16*x,sy + 16*y,
415 						cliprect,TRANSPARENCY_COLOR,trans_color);
416 				}
417 			}
418 		}
419 	}
420 }
421 
422 
phozon_draw_sprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect)423 static void phozon_draw_sprites( struct mame_bitmap *bitmap, const struct rectangle *cliprect )
424 {
425 	int offs;
426 
427 	for (offs = 0;offs < 0x80;offs += 2)
428 	{
429 		/* is it on? */
430 		if ((spriteram_3[offs+1] & 2) == 0)
431 		{
432 			static int size[4] = { 1, 0, 3, 0 };	/* 16, 8, 32 pixels; fourth combination unused? */
433 			static int gfx_offs[4][4] =
434 			{
435 				{ 0, 1, 4, 5 },
436 				{ 2, 3, 6, 7 },
437 				{ 8, 9,12,13 },
438 				{10,11,14,15 }
439 			};
440 			int sprite = (spriteram[offs] << 2) | ((spriteram_3[offs] & 0xc0) >> 6);
441 			int color = spriteram[offs+1] & 0x3f;
442 			int sx = spriteram_2[offs+1] + 0x100 * (spriteram_3[offs+1] & 1) - 69;
443 			int sy = 256 - spriteram_2[offs];
444 			int flipx = (spriteram_3[offs] & 0x01);
445 			int flipy = (spriteram_3[offs] & 0x02) >> 1;
446 			int sizex = size[(spriteram_3[offs] & 0x0c) >> 2];
447 			int sizey = size[(spriteram_3[offs] & 0x30) >> 4];
448 			int x,y;
449 
450 			if (flip_screen)
451 			{
452 				flipx ^= 1;
453 				flipy ^= 1;
454 			}
455 
456 			sy -= 8 * sizey;
457 			sy = (sy & 0xff) - 32;	// fix wraparound
458 
459 			for (y = 0;y <= sizey;y++)
460 			{
461 				for (x = 0;x <= sizex;x++)
462 				{
463 					drawgfx(bitmap,Machine->gfx[1],
464 						sprite + gfx_offs[y ^ (sizey * flipy)][x ^ (sizex * flipx)],
465 						color,
466 						flipx,flipy,
467 						sx + 8*x,sy + 8*y,
468 						cliprect,TRANSPARENCY_COLOR,31);
469 				}
470 			}
471 		}
472 	}
473 }
474 
475 
VIDEO_UPDATE(superpac)476 VIDEO_UPDATE( superpac )
477 {
478 	int x,y;
479 
480 	tilemap_draw(bitmap,cliprect,bg_tilemap,0|TILEMAP_IGNORE_TRANSPARENCY,0);
481 	tilemap_draw(bitmap,cliprect,bg_tilemap,1|TILEMAP_IGNORE_TRANSPARENCY,0);
482 
483 	fillbitmap(sprite_bitmap,15,cliprect);
484 	mappy_draw_sprites(sprite_bitmap,cliprect,0,0,15);
485 	copybitmap(bitmap,sprite_bitmap,0,0,0,0,cliprect,TRANSPARENCY_PEN,15);
486 
487 	/* Redraw the high priority characters */
488 	tilemap_draw(bitmap,cliprect,bg_tilemap,1,0);
489 
490 	/* sprite color 0 still has priority over that (ghost eyes in Pac 'n Pal) */
491 	for (y = 0;y < sprite_bitmap->height;y++)
492 	{
493 		for (x = 0;x < sprite_bitmap->width;x++)
494 		{
495 			if (read_pixel(sprite_bitmap,x,y) == 0)
496 				plot_pixel(bitmap,x,y,0);
497 		}
498 	}
499 }
500 
VIDEO_UPDATE(phozon)501 VIDEO_UPDATE( phozon )
502 {
503 	/* flip screen control is embedded in RAM */
504 	flip_screen_set(mappy_spriteram[0x1f7f-0x800] & 1);
505 
506 	tilemap_draw(bitmap,cliprect,bg_tilemap,0|TILEMAP_IGNORE_TRANSPARENCY,0);
507 	tilemap_draw(bitmap,cliprect,bg_tilemap,1|TILEMAP_IGNORE_TRANSPARENCY,0);
508 
509 	phozon_draw_sprites(bitmap,cliprect);
510 
511 	/* Redraw the high priority characters */
512 	tilemap_draw(bitmap,cliprect,bg_tilemap,1,0);
513 }
514 
VIDEO_UPDATE(mappy)515 VIDEO_UPDATE( mappy )
516 {
517 	int offs;
518 
519 	for (offs = 2;offs < 34;offs++)
520 		tilemap_set_scrolly(bg_tilemap,offs,mappy_scroll);
521 
522 	tilemap_draw(bitmap,cliprect,bg_tilemap,0|TILEMAP_IGNORE_TRANSPARENCY,0);
523 	tilemap_draw(bitmap,cliprect,bg_tilemap,1|TILEMAP_IGNORE_TRANSPARENCY,0);
524 
525 	mappy_draw_sprites(bitmap,cliprect,0,0,15);
526 
527 	/* Redraw the high priority characters */
528 	tilemap_draw(bitmap,cliprect,bg_tilemap,1,0);
529 }
530