summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/mappy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/mappy.c')
-rw-r--r--src/mame/video/mappy.c590
1 files changed, 590 insertions, 0 deletions
diff --git a/src/mame/video/mappy.c b/src/mame/video/mappy.c
new file mode 100644
index 00000000000..2dfdc872d18
--- /dev/null
+++ b/src/mame/video/mappy.c
@@ -0,0 +1,590 @@
+#include "driver.h"
+#include "video/resnet.h"
+
+
+UINT8 *mappy_videoram;
+UINT8 *mappy_spriteram;
+
+static UINT8 mappy_scroll;
+static tilemap *bg_tilemap;
+
+static mame_bitmap *sprite_bitmap;
+
+static colortable *mappy_colortable;
+
+
+/***************************************************************************
+
+ Convert the color PROMs.
+
+ All games except Phozon have one 32x8 palette PROM and two 256x4 color
+ lookup table PROMs (one for characters, one for sprites), except todruaga
+ which has a larger 1024x4 PROM for sprites.
+ The palette PROM is connected to the RGB output this way:
+
+ bit 7 -- 220 ohm resistor -- BLUE
+ -- 470 ohm resistor -- BLUE
+ -- 220 ohm resistor -- GREEN
+ -- 470 ohm resistor -- GREEN
+ -- 1 kohm resistor -- GREEN
+ -- 220 ohm resistor -- RED
+ -- 470 ohm resistor -- RED
+ bit 0 -- 1 kohm resistor -- RED
+
+ The way how the lookup tables are mapped to palette colors, and priority
+ handling, are controlled by a PAL (SPV-5 in Super Pacman, MPI-4 in Mappy),
+ so the two hardwares work differently.
+ Super Pacman has a special "super priority" for sprite colors, allowing
+ one pen to be over high priority tiles (used by Pac & Pal for ghost eyes),
+ which isn't present in Mappy.
+
+***************************************************************************/
+
+PALETTE_INIT( superpac )
+{
+ static const int resistances[3] = { 1000, 470, 220 };
+ double rweights[3], gweights[3], bweights[2];
+ int i;
+
+ /* compute the color output resistor weights */
+ compute_resistor_weights(0, 255, -1.0,
+ 3, &resistances[0], rweights, 0, 0,
+ 3, &resistances[0], gweights, 0, 0,
+ 2, &resistances[1], bweights, 0, 0);
+
+ /* allocate the colortable */
+ mappy_colortable = colortable_alloc(machine, 32);
+
+ /* create a lookup table for the palette */
+ for (i = 0; i < 32; i++)
+ {
+ int bit0, bit1, bit2;
+ int r, g, b;
+
+ /* red component */
+ bit0 = (color_prom[i] >> 0) & 0x01;
+ bit1 = (color_prom[i] >> 1) & 0x01;
+ bit2 = (color_prom[i] >> 2) & 0x01;
+ r = combine_3_weights(rweights, bit0, bit1, bit2);
+
+ /* green component */
+ bit0 = (color_prom[i] >> 3) & 0x01;
+ bit1 = (color_prom[i] >> 4) & 0x01;
+ bit2 = (color_prom[i] >> 5) & 0x01;
+ g = combine_3_weights(gweights, bit0, bit1, bit2);
+
+ /* blue component */
+ bit0 = (color_prom[i] >> 6) & 0x01;
+ bit1 = (color_prom[i] >> 7) & 0x01;
+ b = combine_2_weights(bweights, bit0, bit1);
+
+ colortable_palette_set_color(mappy_colortable, i, MAKE_RGB(r, g, b));
+ }
+
+ /* color_prom now points to the beginning of the lookup table */
+ color_prom += 32;
+
+ /* characters map to the upper 16 palette entries */
+ for (i = 0; i < 64*4; i++)
+ {
+ UINT8 ctabentry = color_prom[i] & 0x0f;
+ colortable_entry_set_value(mappy_colortable, i, (ctabentry ^ 15) + 0x10);
+ }
+
+ /* sprites map to the lower 16 palette entries */
+ for (i = 64*4; i < 128*4; i++)
+ {
+ UINT8 ctabentry = color_prom[i] & 0x0f;
+ colortable_entry_set_value(mappy_colortable, i, ctabentry);
+ }
+}
+
+PALETTE_INIT( mappy )
+{
+ static const int resistances[3] = { 1000, 470, 220 };
+ double rweights[3], gweights[3], bweights[2];
+ int i;
+
+ /* compute the color output resistor weights */
+ compute_resistor_weights(0, 255, -1.0,
+ 3, &resistances[0], rweights, 0, 0,
+ 3, &resistances[0], gweights, 0, 0,
+ 2, &resistances[1], bweights, 0, 0);
+
+ /* allocate the colortable */
+ mappy_colortable = colortable_alloc(machine, 32);
+
+ /* create a lookup table for the palette */
+ for (i = 0; i < 32; i++)
+ {
+ int bit0, bit1, bit2;
+ int r, g, b;
+
+ /* red component */
+ bit0 = (color_prom[i] >> 0) & 0x01;
+ bit1 = (color_prom[i] >> 1) & 0x01;
+ bit2 = (color_prom[i] >> 2) & 0x01;
+ r = combine_3_weights(rweights, bit0, bit1, bit2);
+
+ /* green component */
+ bit0 = (color_prom[i] >> 3) & 0x01;
+ bit1 = (color_prom[i] >> 4) & 0x01;
+ bit2 = (color_prom[i] >> 5) & 0x01;
+ g = combine_3_weights(gweights, bit0, bit1, bit2);
+
+ /* blue component */
+ bit0 = (color_prom[i] >> 6) & 0x01;
+ bit1 = (color_prom[i] >> 7) & 0x01;
+ b = combine_2_weights(bweights, bit0, bit1);
+
+ colortable_palette_set_color(mappy_colortable, i, MAKE_RGB(r, g, b));
+ }
+
+ /* color_prom now points to the beginning of the lookup table */
+ color_prom += 32;
+
+ /* characters map to the upper 16 palette entries */
+ for (i = 0*4; i < 64*4; i++)
+ {
+ UINT8 ctabentry = color_prom[i] & 0x0f;
+ colortable_entry_set_value(mappy_colortable, i, ctabentry + 0x10);
+ }
+
+ /* sprites map to the lower 16 palette entries */
+ for (i = 64*4; i < machine->drv->total_colors; i++)
+ {
+ UINT8 ctabentry = color_prom[i] & 0x0f;
+ colortable_entry_set_value(mappy_colortable, i, ctabentry);
+ }
+}
+
+
+/***************************************************************************
+
+ In Phozon, the palette PROMs are connected to the RGB output this way:
+
+ bit 3 -- 220 ohm resistor -- RED/GREEN/BLUE
+ -- 470 ohm resistor -- RED/GREEN/BLUE
+ -- 1 kohm resistor -- RED/GREEN/BLUE
+ bit 0 -- 2.2kohm resistor -- RED/GREEN/BLUE
+
+***************************************************************************/
+
+PALETTE_INIT( phozon )
+{
+ static const int resistances[4] = { 2200, 1000, 470, 220 };
+ double rweights[4], gweights[4], bweights[4];
+ int i;
+
+ /* compute the color output resistor weights */
+ compute_resistor_weights(0, 255, -1.0,
+ 4, &resistances[0], rweights, 0, 0,
+ 4, &resistances[0], gweights, 0, 0,
+ 4, &resistances[0], bweights, 0, 0);
+
+ /* allocate the colortable */
+ mappy_colortable = colortable_alloc(machine, 32);
+
+ /* create a lookup table for the palette */
+ for (i = 0; i < 32; i++)
+ {
+ int bit0, bit1, bit2, bit3;
+ int r, g, b;
+
+ /* red component */
+ bit0 = (color_prom[i] >> 0) & 0x01;
+ bit1 = (color_prom[i] >> 1) & 0x01;
+ bit2 = (color_prom[i] >> 2) & 0x01;
+ bit3 = (color_prom[i] >> 3) & 0x01;
+ r = combine_4_weights(rweights, bit0, bit1, bit2, bit3);
+
+ /* green component */
+ bit0 = (color_prom[i + 0x100] >> 0) & 0x01;
+ bit1 = (color_prom[i + 0x100] >> 1) & 0x01;
+ bit2 = (color_prom[i + 0x100] >> 2) & 0x01;
+ bit3 = (color_prom[i + 0x100] >> 3) & 0x01;
+ g = combine_4_weights(gweights, bit0, bit1, bit2, bit3);
+
+ /* blue component */
+ bit0 = (color_prom[i + 0x200] >> 0) & 0x01;
+ bit1 = (color_prom[i + 0x200] >> 1) & 0x01;
+ bit2 = (color_prom[i + 0x200] >> 2) & 0x01;
+ bit3 = (color_prom[i + 0x200] >> 3) & 0x01;
+ b = combine_4_weights(bweights, bit0, bit1, bit2, bit3);
+
+ colortable_palette_set_color(mappy_colortable, i, MAKE_RGB(r, g, b));
+ }
+
+ /* color_prom now points to the beginning of the lookup table */
+ color_prom += 0x300;
+
+ /* characters map to the lower 16 palette entries */
+ for (i = 0; i < 64*4; i++)
+ {
+ UINT8 ctabentry = color_prom[i] & 0x0f;
+ colortable_entry_set_value(mappy_colortable, i, ctabentry);
+ }
+
+ /* sprites map to the upper 16 palette entries */
+ for (i = 64*4; i < 128*4; i++)
+ {
+ UINT8 ctabentry = color_prom[i] & 0x0f;
+ colortable_entry_set_value(mappy_colortable, i, ctabentry + 0x10);
+ }
+}
+
+
+
+/***************************************************************************
+
+ Callbacks for the TileMap code
+
+***************************************************************************/
+
+/* convert from 32x32 to 36x28 */
+static TILEMAP_MAPPER( superpac_tilemap_scan )
+{
+ int offs;
+
+ row += 2;
+ col -= 2;
+ if (col & 0x20)
+ offs = row + ((col & 0x1f) << 5);
+ else
+ offs = col + (row << 5);
+
+ return offs;
+}
+
+/* tilemap is a composition of a 32x60 scrolling portion and two 2x28 fixed portions on the sides */
+static TILEMAP_MAPPER( mappy_tilemap_scan )
+{
+ int offs;
+
+ col -= 2;
+ if (col & 0x20)
+ {
+ /* in the following code, note the +2 followed by & 0x0f. This causes unintuitive
+ mapping from logical to hardware coordinates, which is true to the hardware.
+ Not doing it that way would cause missing tiles in motos and todruaga */
+ if (row & 0x20)
+ offs = 0x7ff; // outside visible area
+ else
+ offs = ((row + 2) & 0x0f) + (row & 0x10) + ((col & 3) << 5) + 0x780;
+ }
+ else
+ offs = col + (row << 5);
+
+ return offs;
+}
+
+static TILE_GET_INFO( superpac_get_tile_info )
+{
+ UINT8 attr = mappy_videoram[tile_index + 0x400];
+ tileinfo->category = (attr & 0x40) >> 6;
+ tileinfo->group = attr & 0x3f;
+ SET_TILE_INFO(
+ 0,
+ mappy_videoram[tile_index],
+ attr & 0x3f,
+ 0);
+}
+
+static TILE_GET_INFO( phozon_get_tile_info )
+{
+ UINT8 attr = mappy_videoram[tile_index + 0x400];
+ tileinfo->category = (attr & 0x40) >> 6;
+ tileinfo->group = attr & 0x3f;
+ SET_TILE_INFO(
+ 0,
+ mappy_videoram[tile_index] + ((attr & 0x80) << 1),
+ attr & 0x3f,
+ 0);
+}
+
+static TILE_GET_INFO( mappy_get_tile_info )
+{
+ UINT8 attr = mappy_videoram[tile_index + 0x800];
+ tileinfo->category = (attr & 0x40) >> 6;
+ tileinfo->group = attr & 0x3f;
+ SET_TILE_INFO(
+ 0,
+ mappy_videoram[tile_index],
+ attr & 0x3f,
+ 0);
+}
+
+
+
+/***************************************************************************
+
+ Start the video hardware emulation.
+
+***************************************************************************/
+
+VIDEO_START( superpac )
+{
+ bg_tilemap = tilemap_create(superpac_get_tile_info,superpac_tilemap_scan,TILEMAP_TYPE_PEN,8,8,36,28);
+ sprite_bitmap = auto_bitmap_alloc(machine->screen[0].width,machine->screen[0].height,machine->screen[0].format);
+
+ colortable_configure_tilemap_groups(mappy_colortable, bg_tilemap, machine->gfx[0], 31);
+
+ spriteram = mappy_spriteram + 0x780;
+ spriteram_2 = spriteram + 0x800;
+ spriteram_3 = spriteram_2 + 0x800;
+}
+
+VIDEO_START( phozon )
+{
+ bg_tilemap = tilemap_create(phozon_get_tile_info,superpac_tilemap_scan,TILEMAP_TYPE_PEN,8,8,36,28);
+
+ colortable_configure_tilemap_groups(mappy_colortable, bg_tilemap, machine->gfx[0], 15);
+
+ spriteram = mappy_spriteram + 0x780;
+ spriteram_2 = spriteram + 0x800;
+ spriteram_3 = spriteram_2 + 0x800;
+}
+
+VIDEO_START( mappy )
+{
+ bg_tilemap = tilemap_create(mappy_get_tile_info,mappy_tilemap_scan,TILEMAP_TYPE_PEN,8,8,36,60);
+
+ colortable_configure_tilemap_groups(mappy_colortable, bg_tilemap, machine->gfx[0], 31);
+ tilemap_set_scroll_cols(bg_tilemap, 36);
+
+ spriteram = mappy_spriteram + 0x780;
+ spriteram_2 = spriteram + 0x800;
+ spriteram_3 = spriteram_2 + 0x800;
+}
+
+
+
+/***************************************************************************
+
+ Memory handlers
+
+***************************************************************************/
+
+WRITE8_HANDLER( superpac_videoram_w )
+{
+ mappy_videoram[offset] = data;
+ tilemap_mark_tile_dirty(bg_tilemap,offset & 0x3ff);
+}
+
+WRITE8_HANDLER( mappy_videoram_w )
+{
+ mappy_videoram[offset] = data;
+ tilemap_mark_tile_dirty(bg_tilemap,offset & 0x7ff);
+}
+
+WRITE8_HANDLER( superpac_flipscreen_w )
+{
+ flip_screen_set(data & 1);
+}
+
+READ8_HANDLER( superpac_flipscreen_r )
+{
+ flip_screen_set(1);
+ return 0xff;
+}
+
+WRITE8_HANDLER( mappy_scroll_w )
+{
+ mappy_scroll = offset >> 3;
+}
+
+
+
+/***************************************************************************
+
+ Display refresh
+
+***************************************************************************/
+
+/* also used by toypop.c */
+void mappy_draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect, int xoffs, int yoffs, colortable *ctable, int transcolor)
+{
+ int offs;
+
+ for (offs = 0;offs < 0x80;offs += 2)
+ {
+ /* is it on? */
+ if ((spriteram_3[offs+1] & 2) == 0)
+ {
+ static const UINT8 gfx_offs[2][2] =
+ {
+ { 0, 1 },
+ { 2, 3 }
+ };
+ int sprite = spriteram[offs];
+ int color = spriteram[offs+1];
+ int sx = spriteram_2[offs+1] + 0x100 * (spriteram_3[offs+1] & 1) - 40 + xoffs;
+ int sy = 256 - spriteram_2[offs] + yoffs + 1; // sprites are buffered and delayed by one scanline
+ int flipx = (spriteram_3[offs] & 0x01);
+ int flipy = (spriteram_3[offs] & 0x02) >> 1;
+ int sizex = (spriteram_3[offs] & 0x04) >> 2;
+ int sizey = (spriteram_3[offs] & 0x08) >> 3;
+ int x,y;
+
+ sprite &= ~sizex;
+ sprite &= ~(sizey << 1);
+
+ if (flip_screen)
+ {
+ flipx ^= 1;
+ flipy ^= 1;
+ }
+
+ sy -= 16 * sizey;
+ sy = (sy & 0xff) - 32; // fix wraparound
+
+ for (y = 0;y <= sizey;y++)
+ {
+ for (x = 0;x <= sizex;x++)
+ {
+ drawgfx(bitmap,machine->gfx[1],
+ sprite + gfx_offs[y ^ (sizey * flipy)][x ^ (sizex * flipx)],
+ color,
+ flipx,flipy,
+ sx + 16*x,sy + 16*y,
+ cliprect,TRANSPARENCY_PENS,
+ colortable_get_transpen_mask(ctable, machine->gfx[1], color, transcolor));
+ }
+ }
+ }
+ }
+}
+
+
+/*
+sprite format:
+
+spriteram
+0 xxxxxxxx tile number
+1 --xxxxxx color
+
+spriteram_2
+0 xxxxxxxx Y position
+1 xxxxxxxx X position
+
+spriteram_3
+0 xx------ tile number LSB
+0 --xx---- Y size (16, 8, 32, 4?)
+0 ----xx-- X size (16, 8, 32, 4?)
+0 ------x- Y flip
+0 -------x X flip
+1 ------x- disable
+1 -------x X position MSB
+*/
+
+static void phozon_draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect )
+{
+ int offs;
+
+ for (offs = 0;offs < 0x80;offs += 2)
+ {
+ /* is it on? */
+ if ((spriteram_3[offs+1] & 2) == 0)
+ {
+ static const UINT8 size[4] = { 1, 0, 3, 0 }; /* 16, 8, 32 pixels; fourth combination unused? */
+ static const UINT8 gfx_offs[4][4] =
+ {
+ { 0, 1, 4, 5 },
+ { 2, 3, 6, 7 },
+ { 8, 9,12,13 },
+ {10,11,14,15 }
+ };
+ int sprite = (spriteram[offs] << 2) | ((spriteram_3[offs] & 0xc0) >> 6);
+ int color = spriteram[offs+1] & 0x3f;
+ int sx = spriteram_2[offs+1] + 0x100 * (spriteram_3[offs+1] & 1) - 69;
+ int sy = 256 - spriteram_2[offs];
+ int flipx = (spriteram_3[offs] & 0x01);
+ int flipy = (spriteram_3[offs] & 0x02) >> 1;
+ int sizex = size[(spriteram_3[offs] & 0x0c) >> 2];
+ int sizey = size[(spriteram_3[offs] & 0x30) >> 4];
+ int x,y;
+
+ if (flip_screen)
+ {
+ flipx ^= 1;
+ flipy ^= 1;
+ }
+
+ sy -= 8 * sizey;
+ sy = (sy & 0xff) - 32; // fix wraparound
+
+ for (y = 0;y <= sizey;y++)
+ {
+ for (x = 0;x <= sizex;x++)
+ {
+ drawgfx(bitmap,machine->gfx[1],
+ sprite + gfx_offs[y ^ (sizey * flipy)][x ^ (sizex * flipx)],
+ color,
+ flipx,flipy,
+ sx + 8*x,sy + 8*y,
+ cliprect,TRANSPARENCY_PENS,
+ colortable_get_transpen_mask(mappy_colortable, machine->gfx[1], color, 31));
+ }
+ }
+ }
+ }
+}
+
+
+VIDEO_UPDATE( superpac )
+{
+ int x,y;
+
+ tilemap_draw(bitmap,cliprect,bg_tilemap,0|TILEMAP_DRAW_OPAQUE,0);
+ tilemap_draw(bitmap,cliprect,bg_tilemap,1|TILEMAP_DRAW_OPAQUE,0);
+
+ fillbitmap(sprite_bitmap,15,cliprect);
+ mappy_draw_sprites(machine,sprite_bitmap,cliprect,0,0,mappy_colortable,15);
+ copybitmap(bitmap,sprite_bitmap,0,0,0,0,cliprect,TRANSPARENCY_PEN,15);
+
+ /* Redraw the high priority characters */
+ tilemap_draw(bitmap,cliprect,bg_tilemap,1,0);
+
+ /* sprite color 0 still has priority over that (ghost eyes in Pac 'n Pal) */
+ for (y = 0;y < sprite_bitmap->height;y++)
+ {
+ for (x = 0;x < sprite_bitmap->width;x++)
+ {
+ if (*BITMAP_ADDR16(sprite_bitmap, y, x) == 0)
+ *BITMAP_ADDR16(bitmap, y, x) = 0;
+ }
+ }
+ return 0;
+}
+
+VIDEO_UPDATE( phozon )
+{
+ /* flip screen control is embedded in RAM */
+ flip_screen_set(mappy_spriteram[0x1f7f-0x800] & 1);
+
+ tilemap_draw(bitmap,cliprect,bg_tilemap,0|TILEMAP_DRAW_OPAQUE,0);
+ tilemap_draw(bitmap,cliprect,bg_tilemap,1|TILEMAP_DRAW_OPAQUE,0);
+
+ phozon_draw_sprites(machine,bitmap,cliprect);
+
+ /* Redraw the high priority characters */
+ tilemap_draw(bitmap,cliprect,bg_tilemap,1,0);
+ return 0;
+}
+
+VIDEO_UPDATE( mappy )
+{
+ int offs;
+
+ for (offs = 2;offs < 34;offs++)
+ tilemap_set_scrolly(bg_tilemap,offs,mappy_scroll);
+
+ tilemap_draw(bitmap,cliprect,bg_tilemap,0|TILEMAP_DRAW_OPAQUE,0);
+ tilemap_draw(bitmap,cliprect,bg_tilemap,1|TILEMAP_DRAW_OPAQUE,0);
+
+ mappy_draw_sprites(machine,bitmap,cliprect,0,0,mappy_colortable,15);
+
+ /* Redraw the high priority characters */
+ tilemap_draw(bitmap,cliprect,bg_tilemap,1,0);
+ return 0;
+}