/*************************************************************************** Star Fire video system ***************************************************************************/ #include "driver.h" #include "includes/starfire.h" /* local allocated storage */ static UINT8 *scanline_dirty; static UINT8 starfire_vidctrl; static UINT8 starfire_vidctrl1; static UINT8 starfire_color; /************************************* * * Initialize the video system * *************************************/ VIDEO_START( starfire ) { /* make a temporary bitmap */ tmpbitmap = auto_bitmap_alloc(machine->screen[0].width, machine->screen[0].height, machine->screen[0].format); /* make a dirty array */ scanline_dirty = auto_malloc(STARFIRE_VTOTAL); /* reset videoram */ memset(starfire_videoram, 0, 0x2000); memset(starfire_colorram, 0, 0x2000); memset(scanline_dirty, 1, 256); } /************************************* * * Video control writes * *************************************/ WRITE8_HANDLER( starfire_vidctrl_w ) { starfire_vidctrl = data; } WRITE8_HANDLER( starfire_vidctrl1_w ) { starfire_vidctrl1 = data; } /************************************* * * Color RAM read/writes * *************************************/ WRITE8_HANDLER( starfire_colorram_w ) { /* handle writes to the pseudo-color RAM */ if ((offset & 0xe0) == 0) { int palette_index = (offset & 0x1f) | ((offset & 0x200) >> 4); /* set RAM regardless */ starfire_colorram[offset & ~0x100] = data; starfire_colorram[offset | 0x100] = data; /* don't modify the palette unless the TRANS bit is set */ starfire_color = data & 0x1f; if (!(starfire_vidctrl1 & 0x40)) return; palette_set_color_rgb(Machine, palette_index, pal3bit((data << 1) & 0x06) | ((offset >> 8) & 0x01), pal3bit(data >> 5), pal3bit(data >> 2)); } /* handle writes to the rest of color RAM */ else { /* set RAM based on CDRM */ starfire_colorram[offset] = (starfire_vidctrl1 & 0x80) ? starfire_color : (data & 0x1f); scanline_dirty[offset & 0xff] = 1; starfire_color = data & 0x1f; } } READ8_HANDLER( starfire_colorram_r ) { return starfire_colorram[offset]; } /************************************* * * Video RAM read/writes * *************************************/ WRITE8_HANDLER( starfire_videoram_w ) { int sh, lr, dm, ds, mask, d0, dalu; int offset1 = offset & 0x1fff; int offset2 = (offset + 0x100) & 0x1fff; /* PROT */ if (!(offset & 0xe0) && !(starfire_vidctrl1 & 0x20)) return; /* selector 6A */ if (offset & 0x2000) { sh = (starfire_vidctrl >> 1) & 0x07; lr = starfire_vidctrl & 0x01; } else { sh = (starfire_vidctrl >> 5) & 0x07; lr = (starfire_vidctrl >> 4) & 0x01; } /* mirror bits 5B/5C/5D/5E */ dm = data; if (lr) dm = ((dm & 0x01) << 7) | ((dm & 0x02) << 5) | ((dm & 0x04) << 3) | ((dm & 0x08) << 1) | ((dm & 0x10) >> 1) | ((dm & 0x20) >> 3) | ((dm & 0x40) >> 5) | ((dm & 0x80) >> 7); /* shifters 6D/6E */ ds = (dm << 8) >> sh; mask = 0xff00 >> sh; /* ROLL */ if ((offset & 0x1f00) == 0x1f00) { if (starfire_vidctrl1 & 0x10) mask &= 0x00ff; else mask &= 0xff00; } /* ALU 8B/8D */ d0 = (starfire_videoram[offset1] << 8) | starfire_videoram[offset2]; dalu = d0 & ~mask; d0 &= mask; ds &= mask; switch (~starfire_vidctrl1 & 15) { case 0: dalu |= ds ^ mask; break; case 1: dalu |= (ds | d0) ^ mask; break; case 2: dalu |= (ds ^ mask) & d0; break; case 3: dalu |= 0; break; case 4: dalu |= (ds & d0) ^ mask; break; case 5: dalu |= d0 ^ mask; break; case 6: dalu |= ds ^ d0; break; case 7: dalu |= ds & (d0 ^ mask); break; case 8: dalu |= (ds ^ mask) | d0; break; case 9: dalu |= (ds ^ d0) ^ mask; break; case 10: dalu |= d0; break; case 11: dalu |= ds & d0; break; case 12: dalu |= mask; break; case 13: dalu |= ds | (d0 ^ mask); break; case 14: dalu |= ds | d0; break; case 15: dalu |= ds; break; } /* final output */ starfire_videoram[offset1] = dalu >> 8; starfire_videoram[offset2] = dalu; scanline_dirty[offset1 & 0xff] = 1; /* color output */ if (!(offset & 0x2000) && !(starfire_vidctrl1 & 0x80)) { if (mask & 0xff00) starfire_colorram[offset1] = starfire_color; if (mask & 0x00ff) starfire_colorram[offset2] = starfire_color; } } READ8_HANDLER( starfire_videoram_r ) { int sh, mask, d0; int offset1 = offset & 0x1fff; int offset2 = (offset + 0x100) & 0x1fff; /* selector 6A */ if (offset & 0x2000) sh = (starfire_vidctrl >> 1) & 0x07; else sh = (starfire_vidctrl >> 5) & 0x07; /* shifters 6D/6E */ mask = 0xff00 >> sh; /* ROLL */ if ((offset & 0x1f00) == 0x1f00) { if (starfire_vidctrl1 & 0x10) mask &= 0x00ff; else mask &= 0xff00; } /* munge the results */ d0 = (starfire_videoram[offset1] & (mask >> 8)) | (starfire_videoram[offset2] & mask); d0 = (d0 << sh) | (d0 >> (8 - sh)); return d0 & 0xff; } /************************************* * * Periodic screen refresh callback * *************************************/ void starfire_video_update(int scanline, int count) { UINT8 *pix = &starfire_videoram[scanline]; UINT8 *col = &starfire_colorram[scanline]; int x, y; /* update any dirty scanlines in this range */ for (x = 0; x < 256; x += 8) { for (y = 0; y < count; y++) if ((scanline + y) < STARFIRE_VTOTAL && scanline_dirty[scanline + y]) { int data = pix[y]; int color = col[y]; *BITMAP_ADDR16(tmpbitmap, scanline + y, x + 0) = color | ((data >> 2) & 0x20); *BITMAP_ADDR16(tmpbitmap, scanline + y, x + 1) = color | ((data >> 1) & 0x20); *BITMAP_ADDR16(tmpbitmap, scanline + y, x + 2) = color | ((data >> 0) & 0x20); *BITMAP_ADDR16(tmpbitmap, scanline + y, x + 3) = color | ((data << 1) & 0x20); *BITMAP_ADDR16(tmpbitmap, scanline + y, x + 4) = color | ((data << 2) & 0x20); *BITMAP_ADDR16(tmpbitmap, scanline + y, x + 5) = color | ((data << 3) & 0x20); *BITMAP_ADDR16(tmpbitmap, scanline + y, x + 6) = color | ((data << 4) & 0x20); *BITMAP_ADDR16(tmpbitmap, scanline + y, x + 7) = color | ((data << 5) & 0x20); } pix += 256; col += 256; } /* mark them not dirty anymore */ for (y = 0; y < count; y++) if ((scanline + y) < STARFIRE_VTOTAL) scanline_dirty[scanline + y] = 0; } /************************************* * * Standard screen refresh callback * *************************************/ VIDEO_UPDATE( starfire ) { /* copy the bitmap, remapping the colors */ copybitmap_remap(bitmap, tmpbitmap, 0, 0, 0, 0, &machine->screen[0].visarea, TRANSPARENCY_NONE, 0); return 0; }