diff options
Diffstat (limited to 'src/mame/video/mappy.c')
-rw-r--r-- | src/mame/video/mappy.c | 590 |
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; +} |