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