// license:BSD-3-Clause // copyright-holders:Dan Boris, Olivier Galibert, Aaron Giles /*************************************************************************** Star Fire/Fire One system - video hardware ***************************************************************************/ #include "emu.h" #include "includes/starfire.h" /************************************* * * Initialize the video system * *************************************/ void starfire_state::video_start() { m_screen->register_screen_bitmap(m_starfire_screen); m_scanline_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(starfire_state::starfire_scanline_callback),this)); m_scanline_timer->adjust(m_screen->time_until_pos(STARFIRE_VBEND), STARFIRE_VBEND); /* register for state saving */ save_item(NAME(m_starfire_vidctrl)); save_item(NAME(m_starfire_vidctrl1)); save_item(NAME(m_starfire_color)); save_item(NAME(m_starfire_colors)); } /************************************* * * Color RAM read/writes * *************************************/ WRITE8_MEMBER(starfire_state::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 */ int cl = (m_starfire_vidctrl1 & 0x80) ? m_starfire_color : (data & 0x1f); int cr = (data >> 5) | ((offset & 0x100) >> 5); cr |= (m_starfire_vidctrl1 & 0x80) ? (m_starfire_color & 0x10) : (data & 0x10); m_starfire_colorram[offset & ~0x100] = cl; m_starfire_colorram[offset | 0x100] = cr; m_starfire_color = cl; /* don't modify the palette unless the TRANS bit is set */ if (m_starfire_vidctrl1 & 0x40) { m_starfire_colors[palette_index] = ((cl & 0x3) << 7) | ((cr & 0xf) << 3) | ((cl & 0x1c) >> 2); } } /* handle writes to the rest of color RAM */ else { /* set RAM based on CDRM */ m_starfire_colorram[offset] = (m_starfire_vidctrl1 & 0x80) ? m_starfire_color : (data & 0x1f); m_starfire_color = (m_starfire_vidctrl1 & 0x80) ? m_starfire_color : (data & 0x1f); } } READ8_MEMBER(starfire_state::starfire_colorram_r) { /* handle writes to the pseudo-color RAM, which also happen on reads */ if ((offset & 0xe0) == 0) { int palette_index = (offset & 0x1f) | ((offset & 0x200) >> 4); int cl = m_starfire_colorram[offset & ~0x100]; int cr = m_starfire_colorram[offset | 0x100]; /* don't modify the palette unless the TRANS bit is set */ if (m_starfire_vidctrl1 & 0x40) { m_starfire_colors[palette_index] = ((cl & 0x3) << 7) | ((cr & 0xf) << 3) | ((cl & 0x1c) >> 2); } return cl | ((cr & 0x7) << 5); } return m_starfire_colorram[offset]; } /************************************* * * Video RAM read/writes * *************************************/ WRITE8_MEMBER(starfire_state::starfire_videoram_w) { int sh, lr, dm, ds, mask, d0, dalu; int offset1 = offset & 0x1fff; int offset2 = (offset + 0x100) & 0x1fff; /* PROT */ if (!(offset & 0xe0) && !(m_starfire_vidctrl1 & 0x20)) return; /* selector 6A */ if (offset & 0x2000) { sh = (m_starfire_vidctrl >> 1) & 0x07; lr = m_starfire_vidctrl & 0x01; } else { sh = (m_starfire_vidctrl >> 5) & 0x07; lr = (m_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 (m_starfire_vidctrl1 & 0x10) mask &= 0x00ff; else mask &= 0xff00; } /* ALU 8B/8D */ d0 = (m_starfire_videoram[offset1] << 8) | m_starfire_videoram[offset2]; dalu = d0 & ~mask; d0 &= mask; ds &= mask; switch (~m_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 */ m_starfire_videoram[offset1] = dalu >> 8; m_starfire_videoram[offset2] = dalu; /* color output */ if (!(offset & 0x2000) && !(m_starfire_vidctrl1 & 0x80)) { if (mask & 0xff00) m_starfire_colorram[offset1] = m_starfire_color; if (mask & 0x00ff) m_starfire_colorram[offset2] = m_starfire_color; } } READ8_MEMBER(starfire_state::starfire_videoram_r) { int sh, mask, d0; int offset1 = offset & 0x1fff; int offset2 = (offset + 0x100) & 0x1fff; /* selector 6A */ if (offset & 0x2000) sh = (m_starfire_vidctrl >> 1) & 0x07; else sh = (m_starfire_vidctrl >> 5) & 0x07; /* shifters 6D/6E */ mask = 0xff00 >> sh; /* ROLL */ if ((offset & 0x1f00) == 0x1f00) { if (m_starfire_vidctrl1 & 0x10) mask &= 0x00ff; else mask &= 0xff00; } /* munge the results */ d0 = (m_starfire_videoram[offset1] & (mask >> 8)) | (m_starfire_videoram[offset2] & mask); d0 = (d0 << sh) | (d0 >> (8 - sh)); return d0 & 0xff; } /************************************* * * Standard screen refresh callback * *************************************/ void starfire_state::get_pens(pen_t *pens) { offs_t offs; for (offs = 0; offs < STARFIRE_NUM_PENS; offs++) { uint16_t color = m_starfire_colors[offs]; pens[offs] = rgb_t(pal3bit(color >> 6), pal3bit(color >> 3), pal3bit(color >> 0)); } } TIMER_CALLBACK_MEMBER(starfire_state::starfire_scanline_callback) { pen_t pens[STARFIRE_NUM_PENS]; int y = param; get_pens(pens); uint8_t *pix = &m_starfire_videoram[y]; uint8_t *col = &m_starfire_colorram[y]; for (int x = 0; x < 256; x += 8) { int data = pix[0]; int color = col[0]; m_starfire_screen.pix32(y, x + 0) = pens[color | ((data >> 2) & 0x20)]; m_starfire_screen.pix32(y, x + 1) = pens[color | ((data >> 1) & 0x20)]; m_starfire_screen.pix32(y, x + 2) = pens[color | ((data >> 0) & 0x20)]; m_starfire_screen.pix32(y, x + 3) = pens[color | ((data << 1) & 0x20)]; m_starfire_screen.pix32(y, x + 4) = pens[color | ((data << 2) & 0x20)]; m_starfire_screen.pix32(y, x + 5) = pens[color | ((data << 3) & 0x20)]; m_starfire_screen.pix32(y, x + 6) = pens[color | ((data << 4) & 0x20)]; m_starfire_screen.pix32(y, x + 7) = pens[color | ((data << 5) & 0x20)]; pix += 256; col += 256; } y++; if (y >= STARFIRE_VBSTART) y = STARFIRE_VBEND; m_scanline_timer->adjust(m_screen->time_until_pos(y), y); } uint32_t starfire_state::screen_update_starfire(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { copybitmap(bitmap, m_starfire_screen, 0, 0, 0, 0, cliprect); return 0; }