1 // license:BSD-3-Clause
2 // copyright-holders:Robbbert
3 /* Super80.c written by Robbbert, 2005-2010. See the driver source for documentation. */
4
5
6
7 #include "emu.h"
8 #include "includes/super80.h"
9
10
11
12 /**************************** PALETTES for super80m and super80v ******************************************/
13
super80m_palette(palette_device & palette) const14 void super80_state::super80m_palette(palette_device &palette) const
15 {
16 // RGB
17 palette.set_pen_color( 0, rgb_t(0x00, 0x00, 0x00)); // 0 Black
18 palette.set_pen_color( 1, rgb_t(0x00, 0x00, 0x00)); // 1 Black
19 palette.set_pen_color( 2, rgb_t(0x00, 0x00, 0x7f)); // 2 Blue
20 palette.set_pen_color( 3, rgb_t(0x00, 0x00, 0xff)); // 3 Light Blue
21 palette.set_pen_color( 4, rgb_t(0x00, 0x7f, 0x00)); // 4 Green
22 palette.set_pen_color( 5, rgb_t(0x00, 0xff, 0x00)); // 5 Bright Green
23 palette.set_pen_color( 6, rgb_t(0x00, 0x7f, 0x7f)); // 6 Cyan
24 palette.set_pen_color( 7, rgb_t(0x00, 0xff, 0xff)); // 7 Turquoise
25 palette.set_pen_color( 8, rgb_t(0x7f, 0x00, 0x00)); // 8 Dark Red
26 palette.set_pen_color( 9, rgb_t(0xff, 0x00, 0x00)); // 9 Red
27 palette.set_pen_color(10, rgb_t(0x7f, 0x00, 0x7f)); // 10 Purple
28 palette.set_pen_color(11, rgb_t(0xff, 0x00, 0xff)); // 11 Magenta
29 palette.set_pen_color(12, rgb_t(0x7f, 0x7f, 0x00)); // 12 Lime
30 palette.set_pen_color(13, rgb_t(0xff, 0xff, 0x00)); // 13 Yellow
31 palette.set_pen_color(14, rgb_t(0xbf, 0xbf, 0xbf)); // 14 Off White
32 palette.set_pen_color(15, rgb_t(0xff, 0xff, 0xff)); // 15 White
33 // Composite
34 palette.set_pen_color(16, rgb_t(0x00, 0x00, 0x00)); // 0 Black
35 palette.set_pen_color(17, rgb_t(0x80, 0x80, 0x80)); // 1 Grey
36 palette.set_pen_color(18, rgb_t(0x00, 0x00, 0xff)); // 2 Blue
37 palette.set_pen_color(19, rgb_t(0xff, 0xff, 0x80)); // 3 Light Yellow
38 palette.set_pen_color(20, rgb_t(0x00, 0xff, 0x00)); // 4 Green
39 palette.set_pen_color(21, rgb_t(0xff, 0x80, 0xff)); // 5 Light Magenta
40 palette.set_pen_color(22, rgb_t(0x00, 0xff, 0xff)); // 6 Cyan
41 palette.set_pen_color(23, rgb_t(0xff, 0x40, 0x40)); // 7 Light Red
42 palette.set_pen_color(24, rgb_t(0xff, 0x00, 0x00)); // 8 Red
43 palette.set_pen_color(25, rgb_t(0x00, 0x80, 0x80)); // 9 Dark Cyan
44 palette.set_pen_color(26, rgb_t(0xff, 0x00, 0xff)); // 10 Magenta
45 palette.set_pen_color(27, rgb_t(0x80, 0xff, 0x80)); // 11 Light Green
46 palette.set_pen_color(28, rgb_t(0xff, 0xff, 0x00)); // 12 Yellow
47 palette.set_pen_color(29, rgb_t(0x00, 0x00, 0x80)); // 13 Dark Blue
48 palette.set_pen_color(30, rgb_t(0xff, 0xff, 0xff)); // 14 White
49 palette.set_pen_color(31, rgb_t(0x00, 0x00, 0x00)); // 15 Black
50 }
51
52
53
screen_vblank_super80m(bool state)54 void super80_state::screen_vblank_super80m(bool state)
55 {
56 // rising edge
57 if (state)
58 {
59 // if we chose another palette or colour mode, enable it
60 m_palette_index = (m_io_config->read() & 0x60) ? 0 : 16;
61 }
62 }
63
screen_update_super80(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)64 uint32_t super80_state::screen_update_super80(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
65 {
66 address_space& program = m_maincpu->space(AS_PROGRAM);
67
68 m_cass_led = BIT(m_portf0, 5);
69
70 const uint8_t options = m_io_config->read();
71 bool screen_on = BIT(m_portf0, 2) || !BIT(options, 2); // bit 2 of port F0 is high, OR user turned on config switch
72
73 uint8_t fg = 0;
74 if (screen_on)
75 {
76 if (BIT(options, 5))
77 fg = 15; // b&w
78 else
79 fg = 5; // green
80 }
81
82 uint16_t sy = 0;
83 uint16_t ma = m_vidpg;
84 for (uint8_t y = 0; y < 16; y++)
85 {
86 for (uint8_t ra = 0; ra < 10; ra++)
87 {
88 uint16_t *p = &bitmap.pix(sy++);
89
90 for (uint16_t x = 0; x < 32; x++) // done this way to avoid x overflowing on page FF
91 {
92 uint8_t chr = 32;
93 if (screen_on)
94 {
95 chr = program.read_byte(ma | x) & 0x7f;
96 if ((chr >= 0x61) && (chr <= 0x7a))
97 chr &= 0x1f;
98 else
99 chr &= 0x3f;
100 }
101
102 // get pattern of pixels for that character scanline
103 const uint8_t gfx = m_p_chargen[(chr<<4) | ((ra & 8) >> 3) | ((ra & 7) << 1)];
104
105 // Display a scanline of a character
106 *p++ = BIT(gfx, 7) ? fg : 0;
107 *p++ = BIT(gfx, 6) ? fg : 0;
108 *p++ = BIT(gfx, 5) ? fg : 0;
109 *p++ = BIT(gfx, 4) ? fg : 0;
110 *p++ = BIT(gfx, 3) ? fg : 0;
111 *p++ = BIT(gfx, 2) ? fg : 0;
112 *p++ = BIT(gfx, 1) ? fg : 0;
113 *p++ = BIT(gfx, 0) ? fg : 0;
114 }
115 }
116 ma += 32;
117 }
118 return 0;
119 }
120
screen_update_super80d(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)121 uint32_t super80_state::screen_update_super80d(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
122 {
123 address_space& program = m_maincpu->space(AS_PROGRAM);
124 m_cass_led = BIT(m_portf0, 5);
125
126 const uint8_t options = m_io_config->read();
127 bool screen_on = BIT(m_portf0, 2) || !BIT(options, 2); // bit 2 of port F0 is high, OR user turned on config switch
128
129 uint8_t fg = 0;
130 if (screen_on)
131 {
132 if (BIT(options, 5))
133 fg = 15; // b&w
134 else
135 fg = 5; // green
136 }
137
138 uint16_t sy = 0;
139 uint16_t ma = m_vidpg;
140 for (uint8_t y = 0; y < 16; y++)
141 {
142 for (uint8_t ra = 0; ra < 10; ra++)
143 {
144 uint16_t *p = &bitmap.pix(sy++);
145
146 for (uint16_t x = 0; x < 32; x++)
147 {
148 uint8_t chr = 32;
149 if (screen_on)
150 chr = program.read_byte(ma | x);
151
152 // get pattern of pixels for that character scanline
153 const uint8_t gfx = m_p_chargen[((chr & 0x7f)<<4) | ((ra & 8) >> 3) | ((ra & 7) << 1)] ^ ((chr & 0x80) ? 0xff : 0);
154
155 // Display a scanline of a character
156 *p++ = BIT(gfx, 7) ? fg : 0;
157 *p++ = BIT(gfx, 6) ? fg : 0;
158 *p++ = BIT(gfx, 5) ? fg : 0;
159 *p++ = BIT(gfx, 4) ? fg : 0;
160 *p++ = BIT(gfx, 3) ? fg : 0;
161 *p++ = BIT(gfx, 2) ? fg : 0;
162 *p++ = BIT(gfx, 1) ? fg : 0;
163 *p++ = BIT(gfx, 0) ? fg : 0;
164 }
165 }
166 ma+=32;
167 }
168 return 0;
169 }
170
screen_update_super80e(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)171 uint32_t super80_state::screen_update_super80e(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
172 {
173 address_space& program = m_maincpu->space(AS_PROGRAM);
174 m_cass_led = BIT(m_portf0, 5);
175
176 const uint8_t options = m_io_config->read();
177 bool screen_on = BIT(m_portf0, 2) || !BIT(options, 2); // bit 2 of port F0 is high, OR user turned on config switch
178
179 uint8_t fg = 0;
180 if (screen_on)
181 {
182 if (BIT(options, 5))
183 fg = 15; // b&w
184 else
185 fg = 5; // green
186 }
187
188 uint16_t sy = 0;
189 uint16_t ma = m_vidpg;
190 for (uint8_t y = 0; y < 16; y++)
191 {
192 for (uint8_t ra = 0; ra < 10; ra++)
193 {
194 uint16_t *p = &bitmap.pix(sy++);
195
196 for (uint16_t x = 0; x < 32; x++)
197 {
198 uint8_t chr = 32;
199 if (screen_on)
200 chr = program.read_byte(ma | x);
201
202 // get pattern of pixels for that character scanline
203 const uint8_t gfx = m_p_chargen[(chr<<4) | ((ra & 8) >> 3) | ((ra & 7) << 1)];
204
205 // Display a scanline of a character
206 *p++ = BIT(gfx, 7) ? fg : 0;
207 *p++ = BIT(gfx, 6) ? fg : 0;
208 *p++ = BIT(gfx, 5) ? fg : 0;
209 *p++ = BIT(gfx, 4) ? fg : 0;
210 *p++ = BIT(gfx, 3) ? fg : 0;
211 *p++ = BIT(gfx, 2) ? fg : 0;
212 *p++ = BIT(gfx, 1) ? fg : 0;
213 *p++ = BIT(gfx, 0) ? fg : 0;
214 }
215 }
216 ma+=32;
217 }
218 return 0;
219 }
220
screen_update_super80m(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)221 uint32_t super80_state::screen_update_super80m(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
222 {
223 address_space& program = m_maincpu->space(AS_PROGRAM);
224 m_cass_led = BIT(m_portf0, 5);
225
226 const uint8_t options = m_io_config->read();
227
228 // get selected character generator
229 const bool cgen = m_current_charset ^ BIT(options, 4); // bit 0 of port F1 and cgen config switch
230
231 const bool screen_on = BIT(m_portf0, 2) || !BIT(options, 2); // bit 2 of port F0 is high, OR user turned on config switch
232
233 uint8_t fg = 0;
234 if (screen_on)
235 {
236 if (BIT(options, 5))
237 fg = 15; // b&w
238 else
239 fg = 5; // green
240 }
241
242 uint16_t sy = 0;
243 uint16_t ma = m_vidpg;
244 for (uint8_t y = 0; y < 16; y++)
245 {
246 for (uint8_t ra = 0; ra < 10; ra++)
247 {
248 uint16_t *p = &bitmap.pix(sy++);
249
250 for (uint16_t x = 0; x < 32; x++)
251 {
252 uint8_t chr = 32;
253 if (screen_on)
254 chr = program.read_byte(ma | x);
255
256 uint8_t bg = 0;
257 if (!(options & 0x40))
258 {
259 const uint8_t col = program.read_byte(0xfe00 | ma | x); // byte of colour to display
260 fg = m_palette_index + (col & 0x0f);
261 bg = m_palette_index + (col >> 4);
262 }
263
264 // get pattern of pixels for that character scanline
265 uint8_t gfx;
266 if (cgen)
267 gfx = m_p_chargen[(chr<<4) | ((ra & 8) >> 3) | ((ra & 7) << 1)];
268 else
269 gfx = m_p_chargen[0x1000 | ((chr & 0x7f)<<4) | ((ra & 8) >> 3) | ((ra & 7) << 1)] ^ ((chr & 0x80) ? 0xff : 0);
270
271 // Display a scanline of a character
272 *p++ = BIT(gfx, 7) ? fg : bg;
273 *p++ = BIT(gfx, 6) ? fg : bg;
274 *p++ = BIT(gfx, 5) ? fg : bg;
275 *p++ = BIT(gfx, 4) ? fg : bg;
276 *p++ = BIT(gfx, 3) ? fg : bg;
277 *p++ = BIT(gfx, 2) ? fg : bg;
278 *p++ = BIT(gfx, 1) ? fg : bg;
279 *p++ = BIT(gfx, 0) ? fg : bg;
280 }
281 }
282 ma+=32;
283 }
284 return 0;
285 }
286
287
288 /**************************** I/O PORTS *****************************************************************/
289
portf1_w(u8 data)290 void super80_state::portf1_w(u8 data)
291 {
292 m_vidpg = (data & 0xfe) << 8;
293 m_current_charset = BIT(data, 0);
294 }
295
296 /*---------------------------------------------------------------
297
298 Super-80R and Super-80V
299
300 ---------------------------------------------------------------*/
301
302 // we place videoram at 0x0000, colour ram at 0x1000, pcg at 0x2000
low_r(offs_t offset)303 u8 super80r_state::low_r(offs_t offset)
304 {
305 return m_vram[offset];
306 }
307
low_w(offs_t offset,u8 data)308 void super80r_state::low_w(offs_t offset, u8 data)
309 {
310 m_vram[offset] = data; // video
311 }
312
high_r(offs_t offset)313 u8 super80r_state::high_r(offs_t offset)
314 {
315 return m_vram[offset+0x0800]; // video
316 }
317
high_w(offs_t offset,u8 data)318 void super80r_state::high_w(offs_t offset, u8 data)
319 {
320 m_vram[offset+0x0800] = data; // video
321 m_vram[offset+0x2800] = data; // pcg
322 }
323
low_r(offs_t offset)324 u8 super80v_state::low_r(offs_t offset)
325 {
326 if (BIT(m_portf0, 2))
327 return m_vram[offset]; // video
328 else
329 return m_vram[offset+0x1000]; // colour
330 }
331
low_w(offs_t offset,u8 data)332 void super80v_state::low_w(offs_t offset, u8 data)
333 {
334 if (BIT(m_portf0, 2))
335 m_vram[offset] = data; // video
336 else
337 m_vram[offset+0x1000] = data; // colour
338 }
339
high_r(offs_t offset)340 u8 super80v_state::high_r(offs_t offset)
341 {
342 if (!BIT(m_portf0, 2))
343 return m_vram[offset+0x1800]; // colour
344 else
345 if (BIT(m_portf0, 4))
346 return m_vram[offset+0x0800]; // video
347 else
348 return m_p_chargen[offset]; // char rom
349 }
350
high_w(offs_t offset,u8 data)351 void super80v_state::high_w(offs_t offset, u8 data)
352 {
353 if (!BIT(m_portf0, 2))
354 m_vram[offset+0x1800] = data; // colour
355 else
356 {
357 m_vram[offset+0x0800] = data; // video
358
359 if (BIT(m_portf0, 4))
360 m_vram[offset+0x2800] = data; // pcg
361 }
362 }
363
screen_update_super80v(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)364 uint32_t super80v_state::screen_update_super80v(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
365 {
366 m_s_options = m_io_config->read();
367 m_cass_led = BIT(m_portf0, 5);
368 m_crtc->screen_update(screen, bitmap, cliprect);
369 return 0;
370 }
371
MC6845_UPDATE_ROW(super80v_state::crtc_update_row)372 MC6845_UPDATE_ROW( super80v_state::crtc_update_row )
373 {
374 const rgb_t *palette = m_palette->palette()->entry_list_raw();
375 uint32_t *p = &bitmap.pix(y);
376
377 for (uint16_t x = 0; x < x_count; x++) // for each character
378 {
379 uint8_t inv = 0;
380 if (x == cursor_x) inv=0xff;
381 const uint16_t mem = (ma + x) & 0xfff;
382 uint8_t chr = m_vram[mem];
383
384 /* get colour or b&w */
385 uint8_t fg = 5; // green
386 if ((m_s_options & 0x60) == 0x60)
387 fg = 15; // b&w
388
389 uint8_t bg = 0;
390 if (~m_s_options & 0x40)
391 {
392 const uint8_t col = m_vram[mem+0x1000]; // byte of colour to display
393 fg = m_palette_index + (col & 0x0f);
394 bg = m_palette_index + (col >> 4);
395 }
396
397 // if inverse mode, replace any pcgram chrs with inverse chrs
398 if (!BIT(m_portf0, 4) && BIT(chr, 7)) // is it a high chr in inverse mode
399 {
400 inv ^= 0xff; // invert the chr
401 chr &= 0x7f; // and drop bit 7
402 }
403
404 // get pattern of pixels for that character scanline
405 const uint8_t gfx = BIT(chr, 7)
406 ? m_vram[0x2000 | ((chr << 4) | ra)] ^ inv
407 : m_p_chargen[((chr << 4) | ra)] ^ inv;
408
409 // Display a scanline of a character
410 *p++ = palette[BIT(gfx, 7) ? fg : bg];
411 *p++ = palette[BIT(gfx, 6) ? fg : bg];
412 *p++ = palette[BIT(gfx, 5) ? fg : bg];
413 *p++ = palette[BIT(gfx, 4) ? fg : bg];
414 *p++ = palette[BIT(gfx, 3) ? fg : bg];
415 *p++ = palette[BIT(gfx, 2) ? fg : bg];
416 *p++ = palette[BIT(gfx, 1) ? fg : bg];
417 }
418 }
419
420
421