summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/nemesis.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/nemesis.c')
-rw-r--r--src/mame/video/nemesis.c459
1 files changed, 459 insertions, 0 deletions
diff --git a/src/mame/video/nemesis.c b/src/mame/video/nemesis.c
new file mode 100644
index 00000000000..5e8ad3a365d
--- /dev/null
+++ b/src/mame/video/nemesis.c
@@ -0,0 +1,459 @@
+/***************************************************************************
+
+ video.c
+
+***************************************************************************/
+
+#include "driver.h"
+#include <math.h>
+
+UINT16 *nemesis_videoram1b;
+UINT16 *nemesis_videoram2b;
+UINT16 *nemesis_videoram1f;
+UINT16 *nemesis_videoram2f;
+
+UINT16 *nemesis_characterram;
+size_t nemesis_characterram_size;
+UINT16 *nemesis_xscroll1,*nemesis_xscroll2,*nemesis_yscroll;
+UINT16 *nemesis_yscroll1,*nemesis_yscroll2;
+
+static int spriteram_words;
+static int tilemap_flip;
+static int flipscreen;
+
+static tilemap *background, *foreground;
+
+static UINT8 *blank_characterdata; /* pseudo character */
+
+/* gfxram dirty flags */
+
+/* we should be able to draw sprite gfx directly without caching to GfxElements */
+
+static UINT8 *sprite_dirty[8];
+
+static const struct
+{
+ UINT8 width;
+ UINT8 height;
+ UINT8 char_type;
+}
+sprite_data[8] =
+{
+ { 32, 32, 4 }, { 16, 32, 5 }, { 32, 16, 2 }, { 64, 64, 7 },
+ { 8, 8, 0 }, { 16, 8, 6 }, { 8, 16, 3 }, { 16, 16, 1 }
+};
+
+static TILE_GET_INFO( get_bg_tile_info )
+{
+ int code,color,flags;
+ code = nemesis_videoram1f[tile_index];
+ color = nemesis_videoram2f[tile_index];
+ flags = 0;
+ if ( color & 0x80) flags |= TILE_FLIPX;
+ if ( code & 0x0800) flags |= TILE_FLIPY;
+ if ((~code & 0x2000) || ((code & 0xc000) == 0x4000))
+ flags |= TILE_FORCE_LAYER0;
+ if (code & 0xf800) {
+ SET_TILE_INFO( 0, code&0x7ff, color&0x7f, flags );
+ } else {
+ SET_TILE_INFO( 0, 0x800, 0x00, 0 );
+ }
+ tileinfo->category = (code & 0x1000)>>12;
+}
+
+static TILE_GET_INFO( get_fg_tile_info )
+{
+ int code,color,flags;
+ code = nemesis_videoram1b[tile_index];
+ color = nemesis_videoram2b[tile_index];
+ flags = 0;
+ if ( color & 0x80) flags |= TILE_FLIPX;
+ if ( code & 0x0800) flags |= TILE_FLIPY;
+ if ((~code & 0x2000) || ((code & 0xc000) == 0x4000))
+ flags |= TILE_FORCE_LAYER0;
+ if (code & 0xf800) {
+ SET_TILE_INFO( 0, code&0x7ff, color&0x7f, flags );
+ } else {
+ SET_TILE_INFO( 0, 0x800, 0x00, 0 );
+ }
+ tileinfo->category = (code & 0x1000)>>12;
+}
+
+WRITE16_HANDLER( nemesis_gfx_flipx_w )
+{
+ if (ACCESSING_LSB)
+ {
+ flipscreen = data & 0x01;
+ if (flipscreen)
+ tilemap_flip |= TILEMAP_FLIPX;
+ else
+ tilemap_flip &= ~TILEMAP_FLIPX;
+
+ tilemap_set_flip(ALL_TILEMAPS, tilemap_flip);
+ }
+ else
+ {
+ if (data & 0x100)
+ {
+ cpunum_set_input_line_and_vector(1, 0, HOLD_LINE, 0xff);
+ }
+ }
+}
+
+WRITE16_HANDLER( nemesis_gfx_flipy_w )
+{
+ if (ACCESSING_LSB)
+ {
+ if (data & 0x01)
+ tilemap_flip |= TILEMAP_FLIPY;
+ else
+ tilemap_flip &= ~TILEMAP_FLIPY;
+
+ tilemap_set_flip(ALL_TILEMAPS, tilemap_flip);
+ }
+}
+
+WRITE16_HANDLER( nemesis_palette_word_w )
+{
+ int r,g,b,bit1,bit2,bit3,bit4,bit5;
+
+ COMBINE_DATA(paletteram16 + offset);
+ data = paletteram16[offset];
+
+ /* Mish, 30/11/99 - Schematics show the resistor values are:
+ 300 Ohms
+ 620 Ohms
+ 1200 Ohms
+ 2400 Ohms
+ 4700 Ohms
+
+ So the correct weights per bit are 8, 17, 33, 67, 130
+ */
+
+ #define MULTIPLIER 8 * bit1 + 17 * bit2 + 33 * bit3 + 67 * bit4 + 130 * bit5
+
+ bit1=(data >> 0)&1;
+ bit2=(data >> 1)&1;
+ bit3=(data >> 2)&1;
+ bit4=(data >> 3)&1;
+ bit5=(data >> 4)&1;
+ r = MULTIPLIER;
+ bit1=(data >> 5)&1;
+ bit2=(data >> 6)&1;
+ bit3=(data >> 7)&1;
+ bit4=(data >> 8)&1;
+ bit5=(data >> 9)&1;
+ g = MULTIPLIER;
+ bit1=(data >> 10)&1;
+ bit2=(data >> 11)&1;
+ bit3=(data >> 12)&1;
+ bit4=(data >> 13)&1;
+ bit5=(data >> 14)&1;
+ b = MULTIPLIER;
+
+ palette_set_color(Machine,offset,MAKE_RGB(r,g,b));
+}
+
+WRITE16_HANDLER( salamander_palette_word_w )
+{
+ COMBINE_DATA(paletteram16 + offset);
+ offset &= ~1;
+
+ data = ((paletteram16[offset] << 8) & 0xff00) | (paletteram16[offset+1] & 0xff);
+ palette_set_color_rgb(Machine,offset / 2,pal5bit(data >> 0),pal5bit(data >> 5),pal5bit(data >> 10));
+}
+
+WRITE16_HANDLER( nemesis_videoram1b_word_w )
+{
+ COMBINE_DATA(nemesis_videoram1b + offset);
+ tilemap_mark_tile_dirty( foreground,offset );
+}
+WRITE16_HANDLER( nemesis_videoram1f_word_w )
+{
+ COMBINE_DATA(nemesis_videoram1f + offset);
+ tilemap_mark_tile_dirty( background,offset );
+}
+
+WRITE16_HANDLER( nemesis_videoram2b_word_w )
+{
+ COMBINE_DATA(nemesis_videoram2b + offset);
+ tilemap_mark_tile_dirty( foreground,offset );
+}
+WRITE16_HANDLER( nemesis_videoram2f_word_w )
+{
+ COMBINE_DATA(nemesis_videoram2f + offset);
+ tilemap_mark_tile_dirty( background,offset );
+}
+
+
+/* we have to straighten out the 16-bit word into bytes for gfxdecode() to work */
+WRITE16_HANDLER( nemesis_characterram_word_w )
+{
+ UINT16 oldword = nemesis_characterram[offset];
+ COMBINE_DATA(nemesis_characterram + offset);
+ data = nemesis_characterram[offset];
+
+ if (oldword != data)
+ {
+ int i;
+ for (i=0; i<8; i++)
+ {
+ int w = sprite_data[i].width;
+ int h = sprite_data[i].height;
+ sprite_dirty[i][offset * 4 / (w * h)] = 1;
+ }
+ }
+}
+
+
+/* claim a palette dirty array */
+VIDEO_START( nemesis )
+{
+ int i;
+ spriteram_words = spriteram_size / 2;
+
+ background = tilemap_create(
+ get_bg_tile_info, tilemap_scan_rows, TILEMAP_TYPE_PEN, 8,8, 64,32 );
+
+ foreground = tilemap_create(
+ get_fg_tile_info, tilemap_scan_rows, TILEMAP_TYPE_PEN, 8,8, 64,32 );
+
+ tilemap_set_transparent_pen( background, 0 );
+ tilemap_set_transparent_pen( foreground, 0 );
+ tilemap_set_scroll_rows( background, 256 );
+ tilemap_set_scroll_rows( foreground, 256 );
+
+ for (i=0; i<8; i++)
+ {
+ int w = sprite_data[i].width;
+ int h = sprite_data[i].height;
+ int size = 0x20000 / (w * h);
+ sprite_dirty[i] = auto_malloc(size);
+ memset(sprite_dirty[i], 1, size);
+ }
+
+ memset(nemesis_characterram,0,nemesis_characterram_size);
+
+
+ blank_characterdata = auto_malloc(32*8/8*(2048+1));
+ memset(blank_characterdata,0x00,32*8/8*(2048+1));
+ decodechar(machine->gfx[0],0x800,(UINT8 *)blank_characterdata,
+ machine->drv->gfxdecodeinfo[0].gfxlayout);
+
+ flipscreen = 0;
+ tilemap_flip = 0;
+}
+
+static void draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect)
+{
+ /*
+ * 16 bytes per sprite, in memory from 56000-56fff
+ *
+ * byte 0 : relative priority.
+ * byte 2 : size (?) value #E0 means not used., bit 0x01 is flipx
+ 0xc0 is upper 2 bits of zoom.
+ 0x38 is size.
+ * byte 4 : zoom = 0xff
+ * byte 6 : low bits sprite code.
+ * byte 8 : color + hi bits sprite code., bit 0x20 is flipy bit. bit 0x01 is high bit of X pos.
+ * byte A : X position.
+ * byte C : Y position.
+ * byte E : not used.
+ */
+
+ int adress; /* start of sprite in spriteram */
+ int sx; /* sprite X-pos */
+ int sy; /* sprite Y-pos */
+ int code; /* start of sprite in obj RAM */
+ int color; /* color of the sprite */
+ int flipx,flipy;
+ int zoom;
+ int char_type;
+ int priority;
+ int size;
+ int w,h;
+ int idx;
+
+ for (priority=256-1; priority>=0; priority--)
+ {
+ for (adress = spriteram_words-8; adress >= 0; adress -= 8)
+ {
+ if((spriteram16[adress] & 0xff)!=priority) continue;
+
+ zoom = spriteram16[adress+2] & 0xff;
+ if (!(spriteram16[adress+2] & 0xff00) && ((spriteram16[adress+3] & 0xff00) != 0xff00))
+ code = spriteram16[adress+3] + ((spriteram16[adress+4] & 0xc0) << 2);
+ else
+ code = (spriteram16[adress+3] & 0xff) + ((spriteram16[adress+4] & 0xc0) << 2);
+
+ if (zoom != 0xFF || code!=0)
+ {
+ size=spriteram16[adress+1];
+ zoom+=(size&0xc0)<<2;
+
+ sx = spriteram16[adress+5]&0xff;
+ sy = spriteram16[adress+6]&0xff;
+ if(spriteram16[adress+4]&1)
+ sx-=0x100; /* fixes left side clip */
+ color = (spriteram16[adress+4] & 0x1e) >> 1;
+ flipx = spriteram16[adress+1] & 0x01;
+ flipy = spriteram16[adress+4] & 0x20;
+
+ idx = (size >> 3) & 7;
+ w = sprite_data[idx].width;
+ h = sprite_data[idx].height;
+ code = code * 8 * 16 / (w * h);
+ char_type = sprite_data[idx].char_type;
+
+ if( zoom )
+ {
+ zoom = ((1<<16)*0x80/zoom) + 0x02ab;
+ if (flipscreen)
+ {
+ sx = 256 - ((zoom * w) >> 16) - sx;
+ sy = 256 - ((zoom * h) >> 16) - sy;
+ flipx = !flipx;
+ flipy = !flipy;
+ }
+ pdrawgfxzoom(bitmap,machine->gfx[char_type],
+ code,
+ color,
+ flipx,flipy,
+ sx,sy,
+ cliprect,TRANSPARENCY_PEN,0,
+ zoom,zoom,
+ 0xfff0 );
+ }
+ } /* if sprite */
+ } /* for loop */
+ } /* priority */
+}
+
+/******************************************************************************/
+
+static void update_gfx(running_machine *machine)
+{
+ int offs,code;
+ int bAnyDirty;
+
+ bAnyDirty = 0;
+ for (offs = spriteram_words - 1;offs >= 0;offs --)
+ {
+ if (sprite_dirty[4][offs])
+ {
+ decodechar(machine->gfx[0],offs,(UINT8 *)nemesis_characterram,
+ machine->drv->gfxdecodeinfo[0].gfxlayout);
+ bAnyDirty = 1;
+ sprite_dirty[4][offs] = 0;
+ }
+ }
+ if( bAnyDirty )
+ {
+ tilemap_mark_all_tiles_dirty( background );
+ tilemap_mark_all_tiles_dirty( foreground );
+ }
+
+ for (offs = 0;offs < spriteram_words;offs += 8)
+ {
+ int char_type;
+ int zoom;
+
+ zoom = spriteram16[offs+2] & 0xff;
+ if (!(spriteram16[offs+2] & 0xff00) && ((spriteram16[offs+3] & 0xff00) != 0xff00))
+ code = spriteram16[offs+3] + ((spriteram16[offs+4] & 0xc0) << 2);
+ else
+ code = (spriteram16[offs+3] & 0xff) + ((spriteram16[offs+4] & 0xc0) << 2);
+
+ if (zoom != 0xFF || code!=0)
+ {
+ int size = spriteram16[offs+1];
+ int idx = (size >> 3) & 7;
+ int w, h;
+
+ w = sprite_data[idx].width;
+ h = sprite_data[idx].height;
+ code = code * 8 * 16 / (w * h);
+ char_type = sprite_data[idx].char_type;
+ if (sprite_dirty[idx][code] == 1)
+ {
+ decodechar(machine->gfx[char_type],code,(UINT8 *)nemesis_characterram,
+ machine->drv->gfxdecodeinfo[char_type].gfxlayout);
+ sprite_dirty[idx][code] = 0;
+ }
+ }
+ }
+}
+
+/******************************************************************************/
+
+VIDEO_UPDATE( nemesis )
+{
+ int offs;
+
+ update_gfx(machine);
+
+ fillbitmap(priority_bitmap,0,cliprect);
+ fillbitmap(bitmap,machine->pens[0],cliprect);
+
+ tilemap_set_scrolly( background, 0, (nemesis_yscroll[0x180] & 0xff) );
+
+ for (offs = 0;offs < 256;offs++)
+ {
+ tilemap_set_scrollx( background, offs,
+ (nemesis_xscroll2[offs] & 0xff) + ((nemesis_xscroll2[0x100 + offs] & 0x01) << 8) - (flipscreen ? 0x107 : 0) );
+ tilemap_set_scrollx( foreground, offs,
+ (nemesis_xscroll1[offs] & 0xff) + ((nemesis_xscroll1[0x100 + offs] & 0x01) << 8) - (flipscreen ? 0x107 : 0) );
+ }
+
+ tilemap_draw(bitmap,cliprect,background,0,1);
+ tilemap_draw(bitmap,cliprect,foreground,0,2);
+ tilemap_draw(bitmap,cliprect,background,1,4);
+ tilemap_draw(bitmap,cliprect,foreground,1,8);
+
+ draw_sprites(machine,bitmap,cliprect);
+ return 0;
+}
+
+VIDEO_UPDATE( salamand )
+{
+ int offs;
+ rectangle clip;
+
+ update_gfx(machine);
+
+ fillbitmap(priority_bitmap,0,cliprect);
+ fillbitmap(bitmap,machine->pens[0],cliprect);
+
+ clip.min_x = 0;
+ clip.max_x = 255;
+
+ tilemap_set_scroll_cols( background, 64 );
+ tilemap_set_scroll_cols( foreground, 64 );
+ tilemap_set_scroll_rows( background, 1 );
+ tilemap_set_scroll_rows( foreground, 1 );
+
+ for (offs = 0; offs < 64; offs++)
+ {
+ tilemap_set_scrolly( background, offs, nemesis_yscroll1[offs] );
+ tilemap_set_scrolly( foreground, offs, nemesis_yscroll2[offs] );
+ }
+
+ for (offs = cliprect->min_y; offs <= cliprect->max_y; offs++)
+ {
+ clip.min_y = offs;
+ clip.max_y = offs;
+
+ tilemap_set_scrollx( background, 0,
+ ((nemesis_xscroll2[offs] & 0xff) + ((nemesis_xscroll2[0x100 + offs] & 1) << 8)) );
+ tilemap_set_scrollx( foreground, 0,
+ ((nemesis_xscroll1[offs] & 0xff) + ((nemesis_xscroll1[0x100 + offs] & 1) << 8)) );
+
+ tilemap_draw(bitmap,&clip,foreground,0,1);
+ tilemap_draw(bitmap,&clip,background,0,2);
+ tilemap_draw(bitmap,&clip,foreground,1,4);
+ tilemap_draw(bitmap,&clip,background,1,8);
+ }
+
+ draw_sprites(machine,bitmap,cliprect);
+ return 0;
+}