1 // license:BSD-3-Clause
2 // copyright-holders:Dan Boris, Olivier Galibert, Aaron Giles
3 /***************************************************************************
4 
5     Star Fire/Fire One system - video hardware
6 
7 ***************************************************************************/
8 
9 #include "emu.h"
10 #include "includes/starfire.h"
11 
12 
13 
14 /*************************************
15  *
16  *  Initialize the video system
17  *
18  *************************************/
19 
video_start()20 void starfire_base_state::video_start()
21 {
22 	m_screen->register_screen_bitmap(m_screen_bitmap);
23 	m_scanline_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(starfire_base_state::scanline_callback),this));
24 	m_scanline_timer->adjust(m_screen->time_until_pos(STARFIRE_VBEND), STARFIRE_VBEND);
25 
26 	/* register for state saving */
27 	save_item(NAME(m_vidctrl));
28 	save_item(NAME(m_vidctrl1));
29 	save_item(NAME(m_color));
30 	save_item(NAME(m_colors));
31 }
32 
33 
34 /*************************************
35  *
36  *  Color RAM read/writes
37  *
38  *************************************/
39 
colorram_w(offs_t offset,uint8_t data)40 void starfire_base_state::colorram_w(offs_t offset, uint8_t data)
41 {
42 	/* handle writes to the pseudo-color RAM */
43 	if ((offset & 0xe0) == 0)
44 	{
45 		int palette_index = (offset & 0x1f) | ((offset & 0x200) >> 4);
46 
47 		/* set RAM regardless */
48 		int cl = (m_vidctrl1 & 0x80) ? m_color : (data & 0x1f);
49 		int cr = (data >> 5) | ((offset & 0x100) >> 5);
50 		cr |= (m_vidctrl1 & 0x80) ? (m_color & 0x10) : (data & 0x10);
51 
52 		m_colorram[offset & ~0x100] = cl;
53 		m_colorram[offset |  0x100] = cr;
54 
55 		m_color = cl;
56 
57 		/* don't modify the palette unless the TRANS bit is set */
58 		if (m_vidctrl1 & 0x40)
59 		{
60 			m_colors[palette_index] = ((cl & 0x3) << 7) | ((cr & 0xf) << 3) | ((cl & 0x1c) >> 2);
61 		}
62 	}
63 
64 	/* handle writes to the rest of color RAM */
65 	else
66 	{
67 		/* set RAM based on CDRM */
68 		m_colorram[offset] = (m_vidctrl1 & 0x80) ? m_color : (data & 0x1f);
69 		m_color = (m_vidctrl1 & 0x80) ? m_color : (data & 0x1f);
70 	}
71 }
72 
colorram_r(offs_t offset)73 uint8_t starfire_base_state::colorram_r(offs_t offset)
74 {
75 	/* handle writes to the pseudo-color RAM, which also happen on reads */
76 	if ((offset & 0xe0) == 0)
77 	{
78 		int palette_index = (offset & 0x1f) | ((offset & 0x200) >> 4);
79 		int cl = m_colorram[offset & ~0x100];
80 		int cr = m_colorram[offset |  0x100];
81 
82 		/* don't modify the palette unless the TRANS bit is set */
83 		if (m_vidctrl1 & 0x40)
84 		{
85 			m_colors[palette_index] = ((cl & 0x3) << 7) | ((cr & 0xf) << 3) | ((cl & 0x1c) >> 2);
86 		}
87 
88 		return cl | ((cr & 0x7) << 5);
89 	}
90 
91 	return m_colorram[offset];
92 }
93 
94 /*************************************
95  *
96  *  Video RAM read/writes
97  *
98  *************************************/
99 
videoram_w(offs_t offset,uint8_t data)100 void starfire_base_state::videoram_w(offs_t offset, uint8_t data)
101 {
102 	int sh, lr, dm, ds, mask, d0, dalu;
103 	int offset1 = offset & 0x1fff;
104 	int offset2 = (offset + 0x100) & 0x1fff;
105 
106 	/* PROT */
107 	if (!(offset & 0xe0) && !(m_vidctrl1 & 0x20))
108 		return;
109 
110 	/* selector 6A */
111 	if (offset & 0x2000)
112 	{
113 		sh = (m_vidctrl >> 1) & 0x07;
114 		lr = m_vidctrl & 0x01;
115 	}
116 	else
117 	{
118 		sh = (m_vidctrl >> 5) & 0x07;
119 		lr = (m_vidctrl >> 4) & 0x01;
120 	}
121 
122 	/* mirror bits 5B/5C/5D/5E */
123 	dm = data;
124 	if (lr)
125 		dm = ((dm & 0x01) << 7) | ((dm & 0x02) << 5) | ((dm & 0x04) << 3) | ((dm & 0x08) << 1) |
126 				((dm & 0x10) >> 1) | ((dm & 0x20) >> 3) | ((dm & 0x40) >> 5) | ((dm & 0x80) >> 7);
127 
128 	/* shifters 6D/6E */
129 	ds = (dm << 8) >> sh;
130 	mask = 0xff00 >> sh;
131 
132 	/* ROLL */
133 	if ((offset & 0x1f00) == 0x1f00)
134 	{
135 		if (m_vidctrl1 & 0x10)
136 			mask &= 0x00ff;
137 		else
138 			mask &= 0xff00;
139 	}
140 
141 	/* ALU 8B/8D */
142 	d0 = (m_videoram[offset1] << 8) | m_videoram[offset2];
143 	dalu = d0 & ~mask;
144 	d0 &= mask;
145 	ds &= mask;
146 	switch (~m_vidctrl1 & 15)
147 	{
148 		case 0:     dalu |= ds ^ mask;              break;
149 		case 1:     dalu |= (ds | d0) ^ mask;       break;
150 		case 2:     dalu |= (ds ^ mask) & d0;       break;
151 		case 3:     dalu |= 0;                      break;
152 		case 4:     dalu |= (ds & d0) ^ mask;       break;
153 		case 5:     dalu |= d0 ^ mask;              break;
154 		case 6:     dalu |= ds ^ d0;                break;
155 		case 7:     dalu |= ds & (d0 ^ mask);       break;
156 		case 8:     dalu |= (ds ^ mask) | d0;       break;
157 		case 9:     dalu |= (ds ^ d0) ^ mask;       break;
158 		case 10:    dalu |= d0;                     break;
159 		case 11:    dalu |= ds & d0;                break;
160 		case 12:    dalu |= mask;                   break;
161 		case 13:    dalu |= ds | (d0 ^ mask);       break;
162 		case 14:    dalu |= ds | d0;                break;
163 		case 15:    dalu |= ds;                     break;
164 	}
165 
166 	/* final output */
167 	m_videoram[offset1] = dalu >> 8;
168 	m_videoram[offset2] = dalu;
169 
170 	/* color output */
171 	if (!(offset & 0x2000) && !(m_vidctrl1 & 0x80))
172 	{
173 		if (mask & 0xff00)
174 			m_colorram[offset1] = m_color;
175 		if (mask & 0x00ff)
176 			m_colorram[offset2] = m_color;
177 	}
178 }
179 
videoram_r(offs_t offset)180 uint8_t starfire_base_state::videoram_r(offs_t offset)
181 {
182 	int sh, mask, d0;
183 	int offset1 = offset & 0x1fff;
184 	int offset2 = (offset + 0x100) & 0x1fff;
185 
186 	/* selector 6A */
187 	if (offset & 0x2000)
188 		sh = (m_vidctrl >> 1) & 0x07;
189 	else
190 		sh = (m_vidctrl >> 5) & 0x07;
191 
192 	/* shifters 6D/6E */
193 	mask = 0xff00 >> sh;
194 
195 	/* ROLL */
196 	if ((offset & 0x1f00) == 0x1f00)
197 	{
198 		if (m_vidctrl1 & 0x10)
199 			mask &= 0x00ff;
200 		else
201 			mask &= 0xff00;
202 	}
203 
204 	/* munge the results */
205 	d0 = (m_videoram[offset1] & (mask >> 8)) | (m_videoram[offset2] & mask);
206 	d0 = (d0 << sh) | (d0 >> (8 - sh));
207 	return d0 & 0xff;
208 }
209 
210 
211 
212 /*************************************
213  *
214  *  Standard screen refresh callback
215  *
216  *************************************/
217 
get_pens(pen_t * pens)218 void starfire_base_state::get_pens(pen_t *pens)
219 {
220 	offs_t offs;
221 
222 	for (offs = 0; offs < STARFIRE_NUM_PENS; offs++)
223 	{
224 		uint16_t color = m_colors[offs];
225 
226 		pens[offs] = rgb_t(pal3bit(color >> 6), pal3bit(color >> 3), pal3bit(color >> 0));
227 	}
228 }
229 
TIMER_CALLBACK_MEMBER(starfire_base_state::scanline_callback)230 TIMER_CALLBACK_MEMBER(starfire_base_state::scanline_callback)
231 {
232 	pen_t pens[STARFIRE_NUM_PENS];
233 	int y = param;
234 
235 	get_pens(pens);
236 
237 	uint8_t *pix = &m_videoram[y];
238 	uint8_t *col = &m_colorram[y];
239 
240 	for (int x = 0; x < 256; x += 8)
241 	{
242 		int data = pix[0];
243 		int color = col[0];
244 
245 		m_screen_bitmap.pix(y, x + 0) = pens[color | ((data >> 2) & 0x20)];
246 		m_screen_bitmap.pix(y, x + 1) = pens[color | ((data >> 1) & 0x20)];
247 		m_screen_bitmap.pix(y, x + 2) = pens[color | ((data >> 0) & 0x20)];
248 		m_screen_bitmap.pix(y, x + 3) = pens[color | ((data << 1) & 0x20)];
249 		m_screen_bitmap.pix(y, x + 4) = pens[color | ((data << 2) & 0x20)];
250 		m_screen_bitmap.pix(y, x + 5) = pens[color | ((data << 3) & 0x20)];
251 		m_screen_bitmap.pix(y, x + 6) = pens[color | ((data << 4) & 0x20)];
252 		m_screen_bitmap.pix(y, x + 7) = pens[color | ((data << 5) & 0x20)];
253 
254 		pix += 256;
255 		col += 256;
256 	}
257 
258 	y++;
259 	if (y >= STARFIRE_VBSTART) y = STARFIRE_VBEND;
260 	m_scanline_timer->adjust(m_screen->time_until_pos(y), y);
261 }
262 
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)263 uint32_t starfire_base_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
264 {
265 	copybitmap(bitmap, m_screen_bitmap, 0, 0, 0, 0, cliprect);
266 
267 	return 0;
268 }
269