summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/namcos86.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/namcos86.c')
-rw-r--r--src/mame/video/namcos86.c400
1 files changed, 400 insertions, 0 deletions
diff --git a/src/mame/video/namcos86.c b/src/mame/video/namcos86.c
new file mode 100644
index 00000000000..e0bdeff26df
--- /dev/null
+++ b/src/mame/video/namcos86.c
@@ -0,0 +1,400 @@
+/*******************************************************************
+
+Namco System 86 Video Hardware
+
+*******************************************************************/
+
+#include "driver.h"
+
+
+UINT8 *rthunder_videoram1, *rthunder_videoram2, *rthunder_spriteram;
+
+static int tilebank;
+static int xscroll[4], yscroll[4]; /* scroll + priority */
+
+static tilemap *bg_tilemap[4];
+
+static int backcolor;
+static const UINT8 *tile_address_prom;
+
+
+/***************************************************************************
+
+ Convert the color PROMs into a more useable format.
+
+ Rolling Thunder has two palette PROMs (512x8 and 512x4) and two 2048x8
+ lookup table PROMs.
+ The palette PROMs are connected to the RGB output this way:
+
+ bit 3 -- 220 ohm resistor -- BLUE
+ -- 470 ohm resistor -- BLUE
+ -- 1 kohm resistor -- BLUE
+ bit 0 -- 2.2kohm resistor -- BLUE
+
+ bit 7 -- 220 ohm resistor -- GREEN
+ -- 470 ohm resistor -- GREEN
+ -- 1 kohm resistor -- GREEN
+ -- 2.2kohm resistor -- GREEN
+ -- 220 ohm resistor -- RED
+ -- 470 ohm resistor -- RED
+ -- 1 kohm resistor -- RED
+ bit 0 -- 2.2kohm resistor -- RED
+
+***************************************************************************/
+
+PALETTE_INIT( namcos86 )
+{
+ int i;
+ int totcolors,totlookup;
+
+
+ totcolors = machine->drv->total_colors;
+ totlookup = machine->drv->color_table_len;
+
+ for (i = 0;i < totcolors;i++)
+ {
+ int bit0,bit1,bit2,bit3,r,g,b;
+
+
+ bit0 = (color_prom[0] >> 0) & 0x01;
+ bit1 = (color_prom[0] >> 1) & 0x01;
+ bit2 = (color_prom[0] >> 2) & 0x01;
+ bit3 = (color_prom[0] >> 3) & 0x01;
+ r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
+ bit0 = (color_prom[0] >> 4) & 0x01;
+ bit1 = (color_prom[0] >> 5) & 0x01;
+ bit2 = (color_prom[0] >> 6) & 0x01;
+ bit3 = (color_prom[0] >> 7) & 0x01;
+ g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
+ bit0 = (color_prom[totcolors] >> 0) & 0x01;
+ bit1 = (color_prom[totcolors] >> 1) & 0x01;
+ bit2 = (color_prom[totcolors] >> 2) & 0x01;
+ bit3 = (color_prom[totcolors] >> 3) & 0x01;
+ b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
+
+ palette_set_color(machine,i,MAKE_RGB(r,g,b));
+ color_prom++;
+ }
+
+ color_prom += totcolors;
+ /* color_prom now points to the beginning of the lookup table */
+
+ /* tiles lookup table */
+ for (i = 0;i < totlookup/2;i++)
+ *(colortable++) = *color_prom++;
+
+ /* sprites lookup table */
+ for (i = 0;i < totlookup/2;i++)
+ *(colortable++) = *(color_prom++) + totcolors/2;
+
+ /* color_prom now points to the beginning of the tile address decode PROM */
+
+ tile_address_prom = color_prom; /* we'll need this at run time */
+}
+
+
+
+
+/***************************************************************************
+
+ Callbacks for the TileMap code
+
+***************************************************************************/
+
+INLINE void get_tile_info(running_machine *machine,tile_data *tileinfo,int tile_index,int layer,UINT8 *vram)
+{
+ int attr = vram[2*tile_index + 1];
+ int tile_offs;
+ if (layer & 2)
+ tile_offs = ((tile_address_prom[((layer & 1) << 4) + (attr & 0x03)] & 0xe0) >> 5) * 0x100;
+ else
+ tile_offs = ((tile_address_prom[((layer & 1) << 4) + ((attr & 0x03) << 2)] & 0x0e) >> 1) * 0x100 + tilebank * 0x800;
+
+ SET_TILE_INFO(
+ (layer & 2) ? 1 : 0,
+ vram[2*tile_index] + tile_offs,
+ attr,
+ 0);
+}
+
+static TILE_GET_INFO( get_tile_info0 ) { get_tile_info(machine,tileinfo,tile_index,0,&rthunder_videoram1[0x0000]); }
+static TILE_GET_INFO( get_tile_info1 ) { get_tile_info(machine,tileinfo,tile_index,1,&rthunder_videoram1[0x1000]); }
+static TILE_GET_INFO( get_tile_info2 ) { get_tile_info(machine,tileinfo,tile_index,2,&rthunder_videoram2[0x0000]); }
+static TILE_GET_INFO( get_tile_info3 ) { get_tile_info(machine,tileinfo,tile_index,3,&rthunder_videoram2[0x1000]); }
+
+
+/***************************************************************************
+
+ Start the video hardware emulation.
+
+***************************************************************************/
+
+VIDEO_START( namcos86 )
+{
+ bg_tilemap[0] = tilemap_create(get_tile_info0,tilemap_scan_rows,TILEMAP_TYPE_PEN,8,8,64,32);
+ bg_tilemap[1] = tilemap_create(get_tile_info1,tilemap_scan_rows,TILEMAP_TYPE_PEN,8,8,64,32);
+ bg_tilemap[2] = tilemap_create(get_tile_info2,tilemap_scan_rows,TILEMAP_TYPE_PEN,8,8,64,32);
+ bg_tilemap[3] = tilemap_create(get_tile_info3,tilemap_scan_rows,TILEMAP_TYPE_PEN,8,8,64,32);
+
+ tilemap_set_transparent_pen(bg_tilemap[0],7);
+ tilemap_set_transparent_pen(bg_tilemap[1],7);
+ tilemap_set_transparent_pen(bg_tilemap[2],7);
+ tilemap_set_transparent_pen(bg_tilemap[3],7);
+
+ spriteram = rthunder_spriteram + 0x1800;
+}
+
+
+
+/***************************************************************************
+
+ Memory handlers
+
+***************************************************************************/
+
+READ8_HANDLER( rthunder_videoram1_r )
+{
+ return rthunder_videoram1[offset];
+}
+
+WRITE8_HANDLER( rthunder_videoram1_w )
+{
+ rthunder_videoram1[offset] = data;
+ tilemap_mark_tile_dirty(bg_tilemap[offset/0x1000],(offset & 0xfff)/2);
+}
+
+READ8_HANDLER( rthunder_videoram2_r )
+{
+ return rthunder_videoram2[offset];
+}
+
+WRITE8_HANDLER( rthunder_videoram2_w )
+{
+ rthunder_videoram2[offset] = data;
+ tilemap_mark_tile_dirty(bg_tilemap[2+offset/0x1000],(offset & 0xfff)/2);
+}
+
+WRITE8_HANDLER( rthunder_tilebank_select_w )
+{
+ int bit = BIT(offset,10);
+ if (tilebank != bit)
+ {
+ tilebank = bit;
+ tilemap_mark_all_tiles_dirty(bg_tilemap[0]);
+ tilemap_mark_all_tiles_dirty(bg_tilemap[1]);
+ }
+}
+
+static void scroll_w(int layer,int offset,int data)
+{
+ switch (offset)
+ {
+ case 0:
+ xscroll[layer] = (xscroll[layer]&0xff)|(data<<8);
+ break;
+ case 1:
+ xscroll[layer] = (xscroll[layer]&0xff00)|data;
+ break;
+ case 2:
+ yscroll[layer] = data;
+ break;
+ }
+}
+
+WRITE8_HANDLER( rthunder_scroll0_w )
+{
+ scroll_w(0,offset,data);
+}
+WRITE8_HANDLER( rthunder_scroll1_w )
+{
+ scroll_w(1,offset,data);
+}
+WRITE8_HANDLER( rthunder_scroll2_w )
+{
+ scroll_w(2,offset,data);
+}
+WRITE8_HANDLER( rthunder_scroll3_w )
+{
+ scroll_w(3,offset,data);
+}
+
+WRITE8_HANDLER( rthunder_backcolor_w )
+{
+ backcolor = data;
+}
+
+
+static int copy_sprites;
+
+READ8_HANDLER( rthunder_spriteram_r )
+{
+ return rthunder_spriteram[offset];
+}
+
+WRITE8_HANDLER( rthunder_spriteram_w )
+{
+ rthunder_spriteram[offset] = data;
+
+ /* a write to this offset tells the sprite chip to buffer the sprite list */
+ if (offset == 0x1ff2)
+ copy_sprites = 1;
+}
+
+
+/***************************************************************************
+
+ Display refresh
+
+***************************************************************************/
+
+/*
+sprite format:
+
+0-3 scratchpad RAM
+4-9 CPU writes here, hardware copies from here to 10-15
+10 xx------ X size (16, 8, 32, 4)
+10 --x----- X flip
+10 ---xx--- X offset inside 32x32 tile
+10 -----xxx tile bank
+11 xxxxxxxx tile number
+12 xxxxxxx- color
+12 -------x X position MSB
+13 xxxxxxxx X position
+14 xxx----- priority
+14 ---xx--- Y offset inside 32x32 tile
+14 -----xx- Y size (16, 8, 32, 4)
+14 -------x Y flip
+15 xxxxxxxx Y position
+*/
+
+static void draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect)
+{
+ const UINT8 *source = &spriteram[0x0800-0x20]; /* the last is NOT a sprite */
+ const UINT8 *finish = &spriteram[0];
+ gfx_element *gfx = machine->gfx[2];
+ gfx_element mygfx = *gfx;
+
+ int sprite_xoffs = spriteram[0x07f5] + ((spriteram[0x07f4] & 1) << 8);
+ int sprite_yoffs = spriteram[0x07f7];
+
+ int bank_sprites = machine->gfx[2]->total_elements / 8;
+
+ while (source >= finish)
+ {
+ static const int sprite_size[4] = { 16, 8, 32, 4 };
+ int attr1 = source[10];
+ int attr2 = source[14];
+ int color = source[12];
+ int flipx = (attr1 & 0x20) >> 5;
+ int flipy = (attr2 & 0x01);
+ int sizex = sprite_size[(attr1 & 0xc0) >> 6];
+ int sizey = sprite_size[(attr2 & 0x06) >> 1];
+ int tx = (attr1 & 0x18) & (~(sizex-1));
+ int ty = (attr2 & 0x18) & (~(sizey-1));
+ int sx = source[13] + ((color & 0x01) << 8);
+ int sy = -source[15] - sizey;
+ int sprite = source[11];
+ int sprite_bank = attr1 & 7;
+ int priority = (source[14] & 0xe0) >> 5;
+ int pri_mask = (0xff << (priority + 1)) & 0xff;
+
+ sprite &= bank_sprites-1;
+ sprite += sprite_bank * bank_sprites;
+ color = color >> 1;
+
+ sx += sprite_xoffs;
+ sy -= sprite_yoffs;
+
+ if (flip_screen)
+ {
+ sx = -sx - sizex;
+ sy = -sy - sizey;
+ flipx ^= 1;
+ flipy ^= 1;
+ }
+
+ sy++; /* sprites are buffered and delayed by one scanline */
+
+ /* change GfxElement parameters to draw only the needed part of the 32x32 tile */
+ mygfx.width = sizex;
+ mygfx.height = sizey;
+ mygfx.gfxdata = gfx->gfxdata + tx + ty * gfx->line_modulo;
+
+ pdrawgfx( bitmap, &mygfx,
+ sprite,
+ color,
+ flipx,flipy,
+ sx & 0x1ff,
+ ((sy + 16) & 0xff) - 16,
+ cliprect,TRANSPARENCY_PEN,0xf, pri_mask);
+
+ source -= 0x10;
+ }
+}
+
+
+static void set_scroll(int layer)
+{
+ static const int xdisp[4] = { 47, 49, 46, 48 };
+ int scrollx,scrolly;
+
+ scrollx = xscroll[layer] - xdisp[layer];
+ scrolly = yscroll[layer] + 9;
+ if (flip_screen)
+ {
+ scrollx = -scrollx;
+ scrolly = -scrolly;
+ }
+ tilemap_set_scrollx(bg_tilemap[layer], 0, scrollx);
+ tilemap_set_scrolly(bg_tilemap[layer], 0, scrolly);
+}
+
+
+VIDEO_UPDATE( namcos86 )
+{
+ int layer;
+
+ /* flip screen is embedded in the sprite control registers */
+ /* can't use flip_screen_set() because the visible area is asymmetrical */
+ flip_screen = spriteram[0x07f6] & 1;
+ tilemap_set_flip(ALL_TILEMAPS,flip_screen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
+ set_scroll(0);
+ set_scroll(1);
+ set_scroll(2);
+ set_scroll(3);
+
+ fillbitmap(priority_bitmap, 0, cliprect);
+
+ fillbitmap(bitmap,machine->remapped_colortable[machine->gfx[0]->color_base + 8*backcolor+7],cliprect);
+
+ for (layer = 0;layer < 8;layer++)
+ {
+ int i;
+
+ for (i = 3;i >= 0;i--)
+ {
+ if (((xscroll[i] & 0x0e00) >> 9) == layer)
+ tilemap_draw_primask(bitmap,cliprect,bg_tilemap[i],0,layer,0);
+ }
+ }
+
+ draw_sprites(machine,bitmap,cliprect);
+ return 0;
+}
+
+
+VIDEO_EOF( namcos86 )
+{
+ if (copy_sprites)
+ {
+ int i,j;
+
+ for (i = 0;i < 0x800;i += 16)
+ {
+ for (j = 10;j < 16;j++)
+ spriteram[i+j] = spriteram[i+j - 6];
+ }
+
+ copy_sprites = 0;
+ }
+}