#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;
}