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