diff options
Diffstat (limited to 'src/mame/video/pacman.c')
-rw-r--r-- | src/mame/video/pacman.c | 603 |
1 files changed, 603 insertions, 0 deletions
diff --git a/src/mame/video/pacman.c b/src/mame/video/pacman.c new file mode 100644 index 00000000000..bff584f1eb5 --- /dev/null +++ b/src/mame/video/pacman.c @@ -0,0 +1,603 @@ +/************************************************************************* + + Namco Pac Man + +************************************************************************** + + This file is used by the Pac Man, Pengo & Jr Pac Man drivers. + + Pengo & Pac Man are almost identical, the only differences being the + extra gfx bank in Pengo, and the need to compensate for an hardware + sprite positioning "bug" in Pac Man. + + Jr Pac Man has the same sprite hardware as Pac Man, the extra bank + from Pengo and a scrolling playfield at the expense of one color per row + for the playfield so it can fit in the same amount of ram. + +**************************************************************************/ + +#include "driver.h" +#include "includes/pacman.h" +#include "video/resnet.h" + +static colortable *pacman_colortable; +static tilemap *bg_tilemap; +static UINT8 charbank; +static UINT8 spritebank; +static UINT8 palettebank; +static UINT8 colortablebank; +static UINT8 flipscreen; +static UINT8 bgpriority; + +static int xoffsethack; +UINT8 *s2650games_spriteram; +UINT8 *s2650games_tileram; + +static rectangle spritevisiblearea = +{ + 2*8, 34*8-1, + 0*8, 28*8-1 +}; + + + +/*************************************************************************** + + Convert the color PROMs into a more useable format. + + + Pac Man has a 32x8 palette PROM and a 256x4 color lookup table PROM. + + Pengo has a 32x8 palette PROM and a 1024x4 color lookup table PROM. + + 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 + + + Jr. Pac Man has two 256x4 palette PROMs (the three msb of the address are + grounded, so the effective colors are only 32) and one 256x4 color lookup + table PROM. + + The palette PROMs are connected to the RGB output this way: + + bit 3 -- 220 ohm resistor -- BLUE + -- 470 ohm resistor -- BLUE + -- 220 ohm resistor -- GREEN + bit 0 -- 470 ohm resistor -- GREEN + + bit 3 -- 1 kohm resistor -- GREEN + -- 220 ohm resistor -- RED + -- 470 ohm resistor -- RED + bit 0 -- 1 kohm resistor -- RED + +***************************************************************************/ + +PALETTE_INIT( pacman ) +{ + 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 */ + pacman_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(pacman_colortable, i, MAKE_RGB(r, g, b)); + } + + /* color_prom now points to the beginning of the lookup table */ + color_prom += 32; + + /* allocate the colortable */ + for (i = 0; i < 64*4; i++) + { + UINT8 ctabentry = color_prom[i] & 0x0f; + + /* first palette bank */ + colortable_entry_set_value(pacman_colortable, i, ctabentry); + + /* second palette bank */ + colortable_entry_set_value(pacman_colortable, i + 64*4, 0x10 + ctabentry); + } +} + +static TILEMAP_MAPPER( pacman_scan_rows ) +{ + int offs; + + row += 2; + col -= 2; + if (col & 0x20) + offs = row + ((col & 0x1f) << 5); + else + offs = col + (row << 5); + + return offs; +} + +static TILE_GET_INFO( pacman_get_tile_info ) +{ + int code = videoram[tile_index] | (charbank << 8); + int attr = (colorram[tile_index] & 0x1f) | (colortablebank << 5) | (palettebank << 6 ); + + SET_TILE_INFO(0,code,attr,0); +} + +/*************************************************************************** + + Start the video hardware emulation. + +***************************************************************************/ + +static void init_save_state(void) +{ + state_save_register_global(charbank); + state_save_register_global(spritebank); + state_save_register_global(palettebank); + state_save_register_global(colortablebank); + state_save_register_global(flipscreen); + state_save_register_global(bgpriority); +} + + +VIDEO_START( pacman ) +{ + init_save_state(); + + charbank = 0; + spritebank = 0; + palettebank = 0; + colortablebank = 0; + flipscreen = 0; + bgpriority = 0; + + /* In the Pac Man based games (NOT Pengo) the first two sprites must be offset */ + /* one pixel to the left to get a more correct placement */ + xoffsethack = 1; + + bg_tilemap = tilemap_create( pacman_get_tile_info, pacman_scan_rows, TILEMAP_TYPE_PEN, 8, 8, 36, 28 ); + + tilemap_set_scrolldx( bg_tilemap, 0, 384 - 288 ); + tilemap_set_scrolldy( bg_tilemap, 0, 264 - 224 ); +} + +WRITE8_HANDLER( pacman_videoram_w ) +{ + videoram[offset] = data; + tilemap_mark_tile_dirty( bg_tilemap, offset ); +} + +WRITE8_HANDLER( pacman_colorram_w ) +{ + colorram[offset] = data; + tilemap_mark_tile_dirty( bg_tilemap, offset ); +} + +WRITE8_HANDLER( pacman_flipscreen_w ) +{ + flipscreen = data & 1; + tilemap_set_flip( bg_tilemap, flipscreen * ( TILEMAP_FLIPX + TILEMAP_FLIPY ) ); +} + + +VIDEO_UPDATE( pacman ) +{ + if (bgpriority != 0) + fillbitmap(bitmap,machine->pens[0],cliprect); + else + tilemap_draw(bitmap,cliprect,bg_tilemap,TILEMAP_DRAW_OPAQUE,0); + + if( spriteram_size ) + { + int offs; + + rectangle spriteclip = spritevisiblearea; + sect_rect(&spriteclip, cliprect); + + /* Draw the sprites. Note that it is important to draw them exactly in this */ + /* order, to have the correct priorities. */ + for (offs = spriteram_size - 2;offs > 2*2;offs -= 2) + { + int color; + int sx,sy; + + sx = 272 - spriteram_2[offs + 1]; + sy = spriteram_2[offs] - 31; + color = ( spriteram[offs + 1] & 0x1f ) | (colortablebank << 5) | (palettebank << 6 ); + + drawgfx(bitmap,machine->gfx[1], + ( spriteram[offs] >> 2 ) | (spritebank << 6), + color, + spriteram[offs] & 1,spriteram[offs] & 2, + sx,sy, + &spriteclip,TRANSPARENCY_PENS, + colortable_get_transpen_mask(pacman_colortable, machine->gfx[1], color & 0x3f, 0)); + + /* also plot the sprite with wraparound (tunnel in Crush Roller) */ + drawgfx(bitmap,machine->gfx[1], + ( spriteram[offs] >> 2 ) | (spritebank << 6), + color, + spriteram[offs] & 1,spriteram[offs] & 2, + sx - 256,sy, + &spriteclip,TRANSPARENCY_PENS, + colortable_get_transpen_mask(pacman_colortable, machine->gfx[1], color & 0x3f, 0)); + } + /* In the Pac Man based games (NOT Pengo) the first two sprites must be offset */ + /* one pixel to the left to get a more correct placement */ + for (offs = 2*2;offs >= 0;offs -= 2) + { + int color; + int sx,sy; + + sx = 272 - spriteram_2[offs + 1]; + sy = spriteram_2[offs] - 31; + color = ( spriteram[offs + 1] & 0x1f ) | (colortablebank << 5) | (palettebank << 6 ); + + drawgfx(bitmap,machine->gfx[1], + ( spriteram[offs] >> 2 ) | (spritebank << 6), + color, + spriteram[offs] & 1,spriteram[offs] & 2, + sx,sy + xoffsethack, + &spriteclip,TRANSPARENCY_PENS, + colortable_get_transpen_mask(pacman_colortable, machine->gfx[1], color & 0x3f, 0)); + + /* also plot the sprite with wraparound (tunnel in Crush Roller) */ + drawgfx(bitmap,machine->gfx[1], + ( spriteram[offs] >> 2 ) | (spritebank << 6), + color, + spriteram[offs] & 2,spriteram[offs] & 1, + sx - 256,sy + xoffsethack, + &spriteclip,TRANSPARENCY_PENS, + colortable_get_transpen_mask(pacman_colortable, machine->gfx[1], color & 0x3f, 0)); + } + } + + if (bgpriority != 0) + tilemap_draw(bitmap,cliprect,bg_tilemap,0,0); + return 0; +} + + +/************************************************************************* + + Sega Pengo + +**************************************************************************/ + +VIDEO_START( pengo ) +{ + init_save_state(); + + charbank = 0; + spritebank = 0; + palettebank = 0; + colortablebank = 0; + flipscreen = 0; + bgpriority = 0; + + xoffsethack = 0; + + bg_tilemap = tilemap_create( pacman_get_tile_info, pacman_scan_rows, TILEMAP_TYPE_PEN, 8, 8, 36, 28 ); +} + +WRITE8_HANDLER( pengo_palettebank_w ) +{ + if (palettebank != data) + { + palettebank = data; + tilemap_mark_all_tiles_dirty( bg_tilemap ); + } +} + +WRITE8_HANDLER( pengo_colortablebank_w ) +{ + if (colortablebank != data) + { + colortablebank = data; + tilemap_mark_all_tiles_dirty( bg_tilemap ); + } +} + +WRITE8_HANDLER( pengo_gfxbank_w ) +{ + if (charbank != (data & 1)) + { + spritebank = data & 1; + charbank = data & 1; + tilemap_mark_all_tiles_dirty( bg_tilemap ); + } +} + + +/************************************************************************* + +Van Van + +**************************************************************************/ + +WRITE8_HANDLER( vanvan_bgcolor_w ) +{ + int c = 0xaa * (data & 1); + palette_set_color(Machine,0,MAKE_RGB(c,c,c)); +} + + +/************************************************************************* + +S2650 Games + +**************************************************************************/ + +static TILE_GET_INFO( s2650_get_tile_info ) +{ + int colbank, code, attr; + + colbank = s2650games_tileram[tile_index & 0x1f] & 0x3; + + code = videoram[tile_index] + (colbank << 8); + attr = colorram[tile_index & 0x1f]; + + SET_TILE_INFO(0,code,attr & 0x1f,0); +} + +VIDEO_START( s2650games ) +{ + init_save_state(); + + charbank = 0; + spritebank = 0; + palettebank = 0; + colortablebank = 0; + flipscreen = 0; + bgpriority = 0; + + xoffsethack = 1; + + bg_tilemap = tilemap_create( s2650_get_tile_info,tilemap_scan_rows,TILEMAP_TYPE_PEN,8,8,32,32 ); + + tilemap_set_scroll_cols(bg_tilemap, 32); +} + +VIDEO_UPDATE( s2650games ) +{ + int offs; + + tilemap_draw(bitmap,cliprect,bg_tilemap,0,0); + + for (offs = spriteram_size - 2;offs > 2*2;offs -= 2) + { + int color; + int sx,sy; + + + sx = 255 - spriteram_2[offs + 1]; + sy = spriteram_2[offs] - 15; + color = spriteram[offs + 1] & 0x1f; + + /* TODO: ?? */ + drawgfx(bitmap,machine->gfx[1], + (spriteram[offs] >> 2) | ((s2650games_spriteram[offs] & 3) << 6), + color, + spriteram[offs] & 1,spriteram[offs] & 2, + sx,sy, + cliprect,TRANSPARENCY_PENS, + colortable_get_transpen_mask(pacman_colortable, machine->gfx[1], color & 0x3f, 0)); + } + /* In the Pac Man based games (NOT Pengo) the first two sprites must be offset */ + /* one pixel to the left to get a more correct placement */ + for (offs = 2*2;offs >= 0;offs -= 2) + { + int color; + int sx,sy; + + + sx = 255 - spriteram_2[offs + 1]; + sy = spriteram_2[offs] - 15; + color = spriteram[offs + 1] & 0x1f; + + /* TODO: ?? */ + drawgfx(bitmap,machine->gfx[1], + (spriteram[offs] >> 2) | ((s2650games_spriteram[offs] & 3)<<6), + color, + spriteram[offs] & 1,spriteram[offs] & 2, + sx,sy + xoffsethack, + cliprect,TRANSPARENCY_PENS, + colortable_get_transpen_mask(pacman_colortable, machine->gfx[1], color & 0x3f, 0)); + } + return 0; +} + +WRITE8_HANDLER( s2650games_videoram_w ) +{ + videoram[offset] = data; + tilemap_mark_tile_dirty(bg_tilemap,offset); +} + +WRITE8_HANDLER( s2650games_colorram_w ) +{ + int i; + colorram[offset & 0x1f] = data; + for (i = offset; i < 0x0400; i += 32) + tilemap_mark_tile_dirty(bg_tilemap, i); +} + +WRITE8_HANDLER( s2650games_scroll_w ) +{ + tilemap_set_scrolly(bg_tilemap, offset, data); +} + +WRITE8_HANDLER( s2650games_tilesbank_w ) +{ + s2650games_tileram[offset] = data; + tilemap_mark_all_tiles_dirty(bg_tilemap); +} + + +/************************************************************************* + +Jr. Pac-Man + +**************************************************************************/ + +/* + 0 - 31 = column 2 - 33 attr (used for all 54 rows) + 64 - 1791 = column 2 - 33 code (54 rows) +1794 - 1821 = column 34 code (28 rows) +1826 - 1853 = column 35 code (28 rows) +1858 - 1885 = column 0 code (28 rows) +1890 - 1917 = column 1 code (28 rows) +1922 - 1949 = column 34 attr (28 rows) +1954 - 1981 = column 35 attr (28 rows) +1986 - 2013 = column 0 attr (28 rows) +2018 - 2045 = column 1 attr (28 rows) +*/ + +static TILEMAP_MAPPER( jrpacman_scan_rows ) +{ + int offs; + + row += 2; + col -= 2; + if ((col & 0x20) && (row & 0x20)) + offs = 0; + else if (col & 0x20) + offs = row + (((col&0x3) | 0x38)<< 5); + else + offs = col + (row << 5); + return offs; +} + +static TILE_GET_INFO( jrpacman_get_tile_info ) +{ + int color_index, code, attr; + if( tile_index < 1792 ) + { + color_index = tile_index & 0x1f; + } + else + { + color_index = tile_index + 0x80; + } + + code = videoram[tile_index] | (charbank << 8); + attr = (videoram[color_index] & 0x1f) | (colortablebank << 5) | (palettebank << 6 ); + + SET_TILE_INFO(0,code,attr,0); +} + +static void jrpacman_mark_tile_dirty( int offset ) +{ + if( offset < 0x20 ) + { + /* line color - mark whole line as dirty */ + int i; + for( i = 2 * 0x20; i < 56 * 0x20; i += 0x20 ) + { + tilemap_mark_tile_dirty( bg_tilemap, offset + i ); + } + } + else if (offset < 1792) + { + /* tiles for playfield */ + tilemap_mark_tile_dirty( bg_tilemap, offset ); + } + else + { + /* tiles & colors for top and bottom two rows */ + tilemap_mark_tile_dirty( bg_tilemap, offset & ~0x80 ); + } +} + +/*************************************************************************** + + Start the video hardware emulation. + +***************************************************************************/ +VIDEO_START( jrpacman ) +{ + init_save_state(); + + charbank = 0; + spritebank = 0; + palettebank = 0; + colortablebank = 0; + flipscreen = 0; + bgpriority = 0; + + xoffsethack = 1; + + bg_tilemap = tilemap_create( jrpacman_get_tile_info,jrpacman_scan_rows,TILEMAP_TYPE_PEN,8,8,36,54 ); + + tilemap_set_transparent_pen( bg_tilemap, 0 ); + tilemap_set_scroll_cols( bg_tilemap, 36 ); +} + +WRITE8_HANDLER( jrpacman_videoram_w ) +{ + videoram[offset] = data; + jrpacman_mark_tile_dirty(offset); +} + +WRITE8_HANDLER( jrpacman_charbank_w ) +{ + if (charbank != (data & 1)) + { + charbank = data & 1; + tilemap_mark_all_tiles_dirty(bg_tilemap); + } +} + +WRITE8_HANDLER( jrpacman_spritebank_w ) +{ + spritebank = (data & 1); +} + +WRITE8_HANDLER( jrpacman_scroll_w ) +{ + int i; + for( i = 2; i < 34; i++ ) + { + tilemap_set_scrolly( bg_tilemap, i, data ); + } +} + +WRITE8_HANDLER( jrpacman_bgpriority_w ) +{ + bgpriority = (data & 1); +} |