1 // license:BSD-3-Clause
2 // copyright-holders:Wilbert Pol
3 /***************************************************************************
4
5 Color Graphics Adapter (CGA) section
6
7
8 Notes on Port 3D8
9 (http://www.clipx.net/ng/interrupts_and_ports/ng2d045.php)
10
11 Port 3D8 - Color/VGA Mode control register
12
13 xx1x xxxx Attribute bit 7. 0=blink, 1=Intesity
14 xxx1 xxxx 640x200 mode
15 xxxx 1xxx Enable video signal
16 xxxx x1xx Select B/W mode
17 xxxx xx1x Select graphics
18 xxxx xxx1 80x25 text
19
20
21 The usage of the above control register for various modes is:
22 xx10 1100 40x25 alpha B/W
23 xx10 1000 40x25 alpha color
24 xx10 1101 80x25 alpha B/W
25 xx10 1001 80x25 alpha color
26 xxx0 1110 320x200 graph B/W
27 xxx0 1010 320x200 graph color
28 xxx1 1110 640x200 graph B/W
29
30
31 PC1512 display notes
32
33 The PC1512 built-in display adaptor is an emulation of IBM's CGA. Unlike a
34 real CGA, it is not built around a real MC6845 controller, and so attempts
35 to get custom video modes out of it may not work as expected. Its 640x200
36 CGA mode can be set up to be a 16-color mode rather than mono.
37
38 If you program it with BIOS calls, the PC1512 behaves just like a real CGA,
39 except:
40
41 - The 'greyscale' text modes (0 and 2) behave just like the 'color'
42 ones (1 and 3). On a color monitor both are in color; on a mono
43 monitor both are in greyscale.
44 - Mode 5 (the 'greyscale' graphics mode) displays in color, using
45 an alternative color palette: Cyan, Red and White.
46 - The undocumented 160x100x16 "graphics" mode works correctly.
47
48 (source John Elliott http://www.seasip.info/AmstradXT/pc1512disp.html)
49
50
51 Cursor signal handling:
52
53 The alpha dots signal is set when a character pixel should be set. This signal is
54 also set when the cursor should be displayed. The following formula for alpha
55 dots is derived from the schematics:
56 ALPHA DOTS = ( ( CURSOR DLY ) AND ( CURSOR BLINK ) ) OR ( ( ( NOT AT7 ) OR CURSOR DLY OR -BLINK OR NOT ENABLE BLINK ) AND ( CHG DOTS ) )
57
58 -CURSOR BLINK = VSYNC DLY (LS393) (changes every 8 vsyncs)
59 -BLINK = -CURSOR BLINK (LS393) (changes every 16 vsyncs)
60 -CURSOR DLY = -CURSOR signal from mc6845 and LS174
61 CHG DOTS = character pixel (from character rom)
62
63 For non-blinking modes this formula reduces to:
64 ALPHA DOTS = ( ( CURSOR DLY ) AND ( CURSOR BLINK ) ) OR ( CHG DOTS )
65
66 This means the cursor switches on/off state every 8 vsyncs.
67
68
69 For blinking modes this formula reduces to:
70 ALPHA DOTS = ( ( CURSOR DLY ) AND ( CURSOR BLINK ) ) OR ( ( ( NOT AT7 ) OR CURSOR DLY OR -BLINK ) AND ( CHG DOTS ) )
71
72 So, at the cursor location the attribute blinking is ignored and only regular
73 cursor blinking takes place (state switches every 8 vsyncs). On non-cursor
74 locations with the highest attribute bits set the character will switch
75 on/off every 16 vsyncs. In all other cases the character is displayed as
76 usual.
77
78
79 TODO:
80 - Update more drivers in MESS and MAME and unify with src/emu/video/pc_cga.c
81 - Separate out more cards/implementations
82
83 ***************************************************************************/
84
85 #include "emu.h"
86 #include "video/mc6845.h"
87 #include "cga.h"
88 #include "video/cgapal.h"
89
90 #define VERBOSE_CGA 0 /* CGA (Color Graphics Adapter) */
91
92 #define CGA_SCREEN_NAME "screen"
93 #define CGA_MC6845_NAME "mc6845_cga"
94
95 #define CGA_LOG(N,M,A) \
96 do { \
97 if(VERBOSE_CGA>=N) \
98 { \
99 if( M ) \
100 logerror("%11.6f: %-24s",machine().time().as_double(),(char*)M ); \
101 logerror A; \
102 } \
103 } while (0)
104
105 enum
106 {
107 CGA_TEXT_INTEN = 0,
108 CGA_TEXT_INTEN_ALT,
109 CGA_TEXT_INTEN_CG,
110 CGA_TEXT_BLINK,
111 CGA_TEXT_BLINK_ALT,
112 CGA_TEXT_BLINK_SI,
113 CGA_GFX_1BPP,
114 CGA_GFX_2BPP,
115 CGA_GFX_4BPPL,
116 CGA_GFX_4BPPH,
117 PC1512_GFX_4BPP
118 };
119
120 /***************************************************************************
121
122 Static declarations
123
124 ***************************************************************************/
125
126 static INPUT_PORTS_START( cga )
127 PORT_START( "cga_config" )
128 PORT_CONFNAME( 0x03, 0x00, "CGA character set")
DEF_STR(Normal)129 PORT_CONFSETTING(0x00, DEF_STR( Normal ))
130 PORT_CONFSETTING(0x01, "Alternative")
131 PORT_CONFNAME( 0x1C, 0x00, "CGA monitor type")
132 PORT_CONFSETTING(0x00, "Colour RGB")
133 PORT_CONFSETTING(0x04, "Mono RGB")
134 PORT_CONFSETTING(0x08, "Colour composite")
135 PORT_CONFSETTING(0x0C, "Television")
136 PORT_CONFSETTING(0x10, "LCD")
137 PORT_CONFNAME( 0xE0, 0x00, "CGA chipset")
138 PORT_CONFSETTING(0x00, "IBM")
139 PORT_CONFSETTING(0x20, "Amstrad PC1512")
140 PORT_CONFSETTING(0x40, "Amstrad PPC512")
141 PORT_CONFSETTING(0x60, "ATI")
142 PORT_CONFSETTING(0x80, "Paradise")
143 INPUT_PORTS_END
144
145
146 static INPUT_PORTS_START( pc1512 )
147 PORT_START( "cga_config" )
148 PORT_CONFNAME( 0x03, 0x03, "CGA character set")
149 PORT_CONFSETTING(0x00, "Greek")
150 PORT_CONFSETTING(0x01, "Danish 2")
151 PORT_CONFSETTING(0x02, "Danish 1")
152 PORT_CONFSETTING(0x03, "Default")
153 PORT_CONFNAME( 0x1C, 0x00, "CGA monitor type")
154 PORT_CONFSETTING(0x00, "Colour RGB")
155 PORT_CONFSETTING(0x04, "Mono RGB")
156 PORT_BIT ( 0xE0, 0x20, IPT_UNUSED ) /* Chipset is always PC1512 */
157 INPUT_PORTS_END
158
159
160 /* Dipswitch for font selection */
161 #define CGA_FONT (m_cga_config->read() & m_font_selection_mask)
162
163 /* Dipswitch for monitor selection */
164 #define CGA_MONITOR (m_cga_config->read()&0x1C)
165 #define CGA_MONITOR_RGB 0x00 /* Colour RGB */
166 #define CGA_MONITOR_MONO 0x04 /* Greyscale RGB */
167 #define CGA_MONITOR_COMPOSITE 0x08 /* Colour composite */
168 #define CGA_MONITOR_TELEVISION 0x0C /* Television */
169 #define CGA_MONITOR_LCD 0x10 /* LCD, eg PPC512 */
170
171
172 /* Dipswitch for chipset selection */
173 /* TODO: Get rid of this; these should be handled by separate classes */
174 #define CGA_CHIPSET (m_cga_config->read() & 0xE0)
175 #define CGA_CHIPSET_IBM 0x00 /* Original IBM CGA */
176 #define CGA_CHIPSET_PC1512 0x20 /* PC1512 CGA subset */
177 #define CGA_CHIPSET_PC200 0x40 /* PC200 in CGA mode */
178 #define CGA_CHIPSET_ATI 0x60 /* ATI (supports Plantronics) */
179 #define CGA_CHIPSET_PARADISE 0x80 /* Paradise (used in PC1640) */
180
181 MC6845_UPDATE_ROW( isa8_cga_device::crtc_update_row )
182 {
183 if (m_update_row_type == -1)
184 return;
185
186 y = m_y;
187 if(m_y >= bitmap.height())
188 return;
189
190 switch (m_update_row_type)
191 {
192 case CGA_TEXT_INTEN:
193 cga_text<false, false, false, false, 8>(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
194 break;
195 case CGA_TEXT_INTEN_ALT:
196 cga_text<false, false, false, true, 8>(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
197 break;
198 case CGA_TEXT_INTEN_CG:
199 cga_text<false, false, true, false, 8>(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
200 break;
201 case CGA_TEXT_BLINK:
202 cga_text<true, false, false, false, 8>(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
203 break;
204 case CGA_TEXT_BLINK_ALT:
205 cga_text<true, false, false, true, 8>(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
206 break;
207 case CGA_TEXT_BLINK_SI:
208 cga_text<true, true, false, false, 8>(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
209 break;
210 case CGA_GFX_1BPP:
211 cga_gfx_1bpp_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
212 break;
213 case CGA_GFX_2BPP:
214 cga_gfx_2bpp_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
215 break;
216 case CGA_GFX_4BPPL:
217 cga_gfx_4bppl_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
218 break;
219 case CGA_GFX_4BPPH:
220 cga_gfx_4bpph_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
221 break;
222 }
223 }
224
225
MC6845_UPDATE_ROW(isa8_cga_pc1512_device::crtc_update_row)226 MC6845_UPDATE_ROW( isa8_cga_pc1512_device::crtc_update_row )
227 {
228 if (m_update_row_type == -1)
229 return;
230
231 switch (m_update_row_type)
232 {
233 case PC1512_GFX_4BPP:
234 pc1512_gfx_4bpp_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
235 break;
236 default:
237 isa8_cga_device::crtc_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
238 break;
239 }
240 }
241
242
243 #define CGA_HCLK (XTAL(14'318'181)/8)
244 #define CGA_LCLK (XTAL(14'318'181)/16)
245
246
247 ROM_START( cga )
248 /* IBM 1501981(CGA) and 1501985(MDA) Character rom */
249 ROM_REGION(0x2000,"gfx1", 0)
250 ROM_LOAD("5788005.u33", 0x00000, 0x2000, CRC(0bf56d70) SHA1(c2a8b10808bf51a3c123ba3eb1e9dd608231916f)) /* "AMI 8412PI // 5788005 // (C) IBM CORP. 1981 // KOREA" */
251 ROM_END
252
253
254 //**************************************************************************
255 // GLOBAL VARIABLES
256 //**************************************************************************
257
258 DEFINE_DEVICE_TYPE(ISA8_CGA, isa8_cga_device, "cga", "IBM Color/Graphics Monitor Adapter")
259
260 //-------------------------------------------------
261 // device_add_mconfig - add device configuration
262 //-------------------------------------------------
263
device_add_mconfig(machine_config & config)264 void isa8_cga_device::device_add_mconfig(machine_config &config)
265 {
266 screen_device &screen(SCREEN(config, CGA_SCREEN_NAME, SCREEN_TYPE_RASTER));
267 screen.set_raw(XTAL(14'318'181), 912, 0, 640, 262, 0, 200);
268 screen.set_screen_update(FUNC(isa8_cga_device::screen_update));
269
270 PALETTE(config, m_palette).set_entries(/* CGA_PALETTE_SETS * 16*/ 65536);
271
272 MC6845(config, m_crtc, XTAL(14'318'181)/16);
273 m_crtc->set_screen(nullptr);
274 m_crtc->set_show_border_area(false);
275 m_crtc->set_char_width(8);
276 m_crtc->set_update_row_callback(FUNC(isa8_cga_device::crtc_update_row));
277 m_crtc->out_hsync_callback().set(FUNC(isa8_cga_device::hsync_changed));
278 m_crtc->out_vsync_callback().set(FUNC(isa8_cga_device::vsync_changed));
279 m_crtc->set_reconfigure_callback(FUNC(isa8_cga_device::reconfigure));
280 }
281
device_input_ports() const282 ioport_constructor isa8_cga_device::device_input_ports() const
283 {
284 return INPUT_PORTS_NAME( cga );
285 }
286
287 //-------------------------------------------------
288 // rom_region - device-specific ROM region
289 //-------------------------------------------------
290
device_rom_region() const291 const tiny_rom_entry *isa8_cga_device::device_rom_region() const
292 {
293 return ROM_NAME( cga );
294 }
295
296
297 //-------------------------------------------------
298 // isa8_cga_device - constructor
299 //-------------------------------------------------
300
isa8_cga_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)301 isa8_cga_device::isa8_cga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
302 isa8_cga_device(mconfig, ISA8_CGA, tag, owner, clock)
303 {
304 }
305
isa8_cga_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)306 isa8_cga_device::isa8_cga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
307 device_t(mconfig, type, tag, owner, clock),
308 device_isa8_card_interface(mconfig, *this),
309 m_crtc(*this, CGA_MC6845_NAME), m_cga_config(*this, "cga_config"), m_framecnt(0), m_mode_control(0), m_color_select(0),
310 m_update_row_type(-1), m_y(0), m_chr_gen_base(nullptr), m_chr_gen(nullptr), m_vsync(0), m_hsync(0),
311 m_vram_size( 0x4000 ), m_plantronics(0),
312 m_palette(*this, "palette"),
313 m_screen(*this, "screen")
314 {
315 m_chr_gen_offset[0] = m_chr_gen_offset[2] = 0x1800;
316 m_chr_gen_offset[1] = m_chr_gen_offset[3] = 0x1000;
317 m_font_selection_mask = 0x01;
318 m_start_offset = 0;
319 m_superimpose = false;
320 }
321
322
323 //-------------------------------------------------
324 // device_start - device-specific startup
325 //-------------------------------------------------
326
device_start()327 void isa8_cga_device::device_start()
328 {
329 if (m_palette != nullptr && !m_palette->started())
330 throw device_missing_dependencies();
331
332 set_isa_device();
333 m_vram.resize(m_vram_size);
334 m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*this, FUNC(isa8_cga_device::io_read)), write8sm_delegate(*this, FUNC(isa8_cga_device::io_write)));
335 m_isa->install_bank(0xb8000, 0xb8000 + (std::min<size_t>)(0x8000, m_vram_size) - 1, "bank_cga", &m_vram[0]);
336 if(m_vram_size == 0x4000)
337 m_isa->install_bank(0xbc000, 0xbffff, "bank_cga", &m_vram[0]);
338
339 /* Initialise the cga palette */
340 int i;
341
342
343 for ( i = 0; i < CGA_PALETTE_SETS * 16; i++ )
344 {
345 m_palette->set_pen_color( i, cga_palette[i][0], cga_palette[i][1], cga_palette[i][2] );
346 }
347
348 i = 0x8000;
349 for ( int r = 0; r < 32; r++ )
350 {
351 for ( int g = 0; g < 32; g++ )
352 {
353 for ( int b = 0; b < 32; b++ )
354 {
355 m_palette->set_pen_color( i, r << 3, g << 3, b << 3 );
356 i++;
357 }
358 }
359 }
360
361 m_chr_gen_base = memregion(subtag("gfx1").c_str())->base();
362 m_chr_gen = m_chr_gen_base + m_chr_gen_offset[1];
363
364 save_item(NAME(m_framecnt));
365 save_item(NAME(m_mode_control));
366 save_item(NAME(m_color_select));
367 //save_item(NAME(m_status)); uncomment when used
368 save_item(NAME(m_update_row_type));
369 save_item(NAME(m_vsync));
370 save_item(NAME(m_hsync));
371 save_item(NAME(m_vram));
372 save_item(NAME(m_plantronics));
373 save_item(NAME(m_y));
374 }
375
376
377 //-------------------------------------------------
378 // device_reset - device-specific reset
379 //-------------------------------------------------
380
device_reset()381 void isa8_cga_device::device_reset()
382 {
383 m_framecnt = 0;
384 m_mode_control = 0;
385 m_vsync = 0;
386 m_hsync = 0;
387 m_color_select = 0;
388 m_y = 0;
389 memset(m_palette_lut_2bpp, 0, sizeof(m_palette_lut_2bpp));
390 }
391
392 /***************************************************************************
393
394 Methods
395
396 ***************************************************************************/
397
398
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)399 uint32_t isa8_cga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
400 {
401 m_crtc->screen_update( screen, bitmap, cliprect);
402
403 /* Check for changes in font dipsetting */
404 switch ( CGA_FONT )
405 {
406 case 0:
407 m_chr_gen = m_chr_gen_base + m_chr_gen_offset[0];
408 break;
409 case 1:
410 m_chr_gen = m_chr_gen_base + m_chr_gen_offset[1];
411 break;
412 case 2:
413 m_chr_gen = m_chr_gen_base + m_chr_gen_offset[2];
414 break;
415 case 3:
416 m_chr_gen = m_chr_gen_base + m_chr_gen_offset[3];
417 break;
418 }
419 return 0;
420 }
421
422
423 DEFINE_DEVICE_TYPE(ISA8_CGA_POISK2, isa8_cga_poisk2_device, "cga_poisk2", "ISA8_CGA_POISK2")
424
425 //-------------------------------------------------
426 // isa8_cga_poisk2_device - constructor
427 //-------------------------------------------------
428
isa8_cga_poisk2_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)429 isa8_cga_poisk2_device::isa8_cga_poisk2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
430 isa8_cga_device(mconfig, ISA8_CGA_POISK2, tag, owner, clock)
431 {
432 m_chr_gen_offset[0] = 0x0000;
433 m_chr_gen_offset[1] = 0x0800;
434 }
435
436 ROM_START( cga_poisk2 )
437 ROM_REGION(0x2000,"gfx1", 0)
CRC(d537f665)438 ROM_LOAD( "p2_ecga.rf4", 0x0000, 0x2000, CRC(d537f665) SHA1(d70f085b9b0cbd53df7c3122fbe7592998ba8fed))
439 ROM_END
440
441 //-------------------------------------------------
442 // rom_region - device-specific ROM region
443 //-------------------------------------------------
444
445 const tiny_rom_entry *isa8_cga_poisk2_device::device_rom_region() const
446 {
447 return ROM_NAME( cga_poisk2 );
448 }
449
450
451 /* for superimposing CGA over a different source video (i.e. tetriskr) */
452 DEFINE_DEVICE_TYPE(ISA8_CGA_SUPERIMPOSE, isa8_cga_superimpose_device, "cga_superimpose", "ISA8_CGA_SUPERIMPOSE")
453
454 //-------------------------------------------------
455 // isa8_cga_superimpose_device - constructor
456 //-------------------------------------------------
457
isa8_cga_superimpose_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)458 isa8_cga_superimpose_device::isa8_cga_superimpose_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
459 isa8_cga_superimpose_device(mconfig, ISA8_CGA_SUPERIMPOSE, tag, owner, clock)
460 {
461 }
462
isa8_cga_superimpose_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)463 isa8_cga_superimpose_device::isa8_cga_superimpose_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
464 isa8_cga_device(mconfig, type, tag, owner, clock)
465 {
466 m_superimpose = true;
467 }
468
469 template<bool blink, bool si, bool comp, bool alt, int width>
MC6845_UPDATE_ROW(isa8_cga_device::cga_text)470 MC6845_UPDATE_ROW( isa8_cga_device::cga_text )
471 {
472 uint8_t const *const videoram = &m_vram[m_start_offset];
473 uint32_t *p = &bitmap.pix(y);
474 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
475
476 if (y == 0) CGA_LOG(1,"cga_text_8",("\n"));
477 for (int i = 0; i < x_count; i++)
478 {
479 uint16_t const offset = ((ma + i) << 1) & 0x3fff;
480 uint8_t const chr = videoram[offset];
481 uint8_t const attr = videoram[offset +1];
482 uint8_t data = m_chr_gen[chr * width + ra];
483 uint16_t fg, bg;
484
485 if (comp)
486 {
487 fg = 0x10 + (attr & 0x0f);
488 bg = alt ? 0 : (0x10 + ((attr >> 4) & 0x07));
489 }
490 else
491 {
492 fg = attr & 0x0F;
493 bg = alt ? 0 : ((attr >> 4) & (blink ? 0x07 : 0x0f));
494 }
495
496 if ((i == cursor_x) && (m_framecnt & 0x08))
497 data = 0xff;
498 else if (blink && (attr & 0x80) && (m_framecnt & 0x10))
499 {
500 data = 0x00;
501 bg = (attr >> 4) & 0x07;
502 }
503
504 for (int xi = 0; xi < 8; xi++)
505 {
506 uint8_t const dot = (data & (1 << (7 - xi)));
507 uint8_t const pen_data = dot ? fg : bg;
508 if (!si || (pen_data || dot))
509 *p = palette[pen_data];
510 p++;
511 }
512 }
513 }
514
515
516 /* The lo-res (320x200) graphics mode on a colour composite monitor */
517
MC6845_UPDATE_ROW(isa8_cga_device::cga_gfx_4bppl_update_row)518 MC6845_UPDATE_ROW( isa8_cga_device::cga_gfx_4bppl_update_row )
519 {
520 uint8_t const *const videoram = &m_vram[m_start_offset];
521 uint32_t *p = &bitmap.pix(y);
522 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
523
524 if (y == 0) CGA_LOG(1,"cga_gfx_4bppl_update_row",("\n"));
525 for (int i = 0; i < x_count; i++)
526 {
527 uint16_t const offset = (((ma + i) << 1) & 0x1fff) | ((y & 1) << 13);
528 uint8_t data;
529
530 data = videoram[offset];
531
532 *p++ = palette[data >> 4];
533 *p++ = palette[data >> 4];
534 *p++ = palette[data & 0x0f];
535 *p++ = palette[data & 0x0f];
536
537 data = videoram[offset + 1];
538
539 *p++ = palette[data >> 4];
540 *p++ = palette[data >> 4];
541 *p++ = palette[data & 0x0f];
542 *p++ = palette[data & 0x0f];
543 }
544 }
545
546
547 #if 0
548 /* The hi-res graphics mode on a colour composite monitor
549 *
550 * The different scaling factors mean that the '160x200' versions of screens
551 * are the same size as the normal colour ones.
552 */
553
554 static const uint8_t yc_lut2[4] = { 0, 182, 71, 255 };
555
556 static const uint8_t yc_lut[16][8] =
557 {
558 { 0, 0, 0, 0, 0, 0, 0, 0 }, /* black */
559 { 0, 0, 0, 0, 1, 1, 1, 1 }, /* blue */
560 { 0, 1, 1, 1, 1, 0, 0, 0 }, /* green */
561 { 0, 0, 1, 1, 1, 1, 0, 0 }, /* cyan */
562 { 1, 1, 0, 0, 0, 0, 1, 1 }, /* red */
563 { 1, 0, 0, 0, 0, 1, 1, 1 }, /* magenta */
564 { 1, 1, 1, 1, 0, 0, 0, 0 }, /* yellow */
565 { 1, 1, 1, 1, 1, 1, 1, 1 }, /* white */
566 /* Intensity set */
567 { 2, 2, 2, 2, 2, 2, 2, 2 }, /* black */
568 { 2, 2, 2, 2, 3, 3, 3, 3 }, /* blue */
569 { 2, 3, 3, 3, 3, 2, 2, 2 }, /* green */
570 { 2, 2, 3, 3, 3, 3, 2, 2 }, /* cyan */
571 { 3, 3, 2, 2, 2, 2, 3, 3 }, /* red */
572 { 3, 2, 2, 2, 2, 3, 3, 3 }, /* magenta */
573 { 3, 3, 3, 3, 2, 2, 2, 2 }, /* yellow */
574 { 3, 3, 3, 3, 3, 3, 3, 3 }, /* white */
575 };
576 #endif
577
MC6845_UPDATE_ROW(isa8_cga_device::cga_gfx_4bpph_update_row)578 MC6845_UPDATE_ROW( isa8_cga_device::cga_gfx_4bpph_update_row )
579 {
580 uint8_t const *const videoram = &m_vram[m_start_offset];
581 uint32_t *p = &bitmap.pix(y);
582 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
583
584 if (y == 0) CGA_LOG(1,"cga_gfx_4bpph_update_row",("\n"));
585 for (int i = 0; i < x_count; i++)
586 {
587 uint16_t const offset = (((ma + i) << 1) & 0x1fff) | ((y & 1) << 13);
588 uint8_t data;
589
590 data = videoram[offset];
591
592 *p++ = palette[data >> 4];
593 *p++ = palette[data >> 4];
594 *p++ = palette[data >> 4];
595 *p++ = palette[data >> 4];
596 *p++ = palette[data & 0x0f];
597 *p++ = palette[data & 0x0f];
598 *p++ = palette[data & 0x0f];
599 *p++ = palette[data & 0x0f];
600
601 data = videoram[offset + 1];
602
603 *p++ = palette[data >> 4];
604 *p++ = palette[data >> 4];
605 *p++ = palette[data >> 4];
606 *p++ = palette[data >> 4];
607 *p++ = palette[data & 0x0f];
608 *p++ = palette[data & 0x0f];
609 *p++ = palette[data & 0x0f];
610 *p++ = palette[data & 0x0f];
611 }
612 }
613
614
615 /***************************************************************************
616 Draw graphics mode with 320x200 pixels (default) with 2 bits/pixel.
617 Even scanlines are from CGA_base + 0x0000, odd from CGA_base + 0x2000
618 cga fetches 2 byte per mc6845 access.
619 ***************************************************************************/
620
MC6845_UPDATE_ROW(isa8_cga_device::cga_gfx_2bpp_update_row)621 MC6845_UPDATE_ROW( isa8_cga_device::cga_gfx_2bpp_update_row )
622 {
623 uint8_t const *const videoram = &m_vram[m_start_offset];
624 uint32_t *p = &bitmap.pix(y);
625 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
626
627 if (y == 0) CGA_LOG(1,"cga_gfx_2bpp_update_row",("\n"));
628 for (int i = 0; i < x_count; i++)
629 {
630 uint16_t const offset = (((ma + i) << 1) & 0x1fff) | ((ra & 1) << 13);
631 uint8_t data;
632
633 data = videoram[offset];
634
635 *p++ = palette[m_palette_lut_2bpp[(data >> 6) & 0x03]];
636 *p++ = palette[m_palette_lut_2bpp[(data >> 4) & 0x03]];
637 *p++ = palette[m_palette_lut_2bpp[(data >> 2) & 0x03]];
638 *p++ = palette[m_palette_lut_2bpp[ data & 0x03]];
639
640 data = videoram[offset + 1];
641
642 *p++ = palette[m_palette_lut_2bpp[(data >> 6) & 0x03]];
643 *p++ = palette[m_palette_lut_2bpp[(data >> 4) & 0x03]];
644 *p++ = palette[m_palette_lut_2bpp[(data >> 2) & 0x03]];
645 *p++ = palette[m_palette_lut_2bpp[ data & 0x03]];
646 }
647 }
648
649
650
651 /***************************************************************************
652 Draw graphics mode with 640x200 pixels (default).
653 The cell size is 1x1 (1 scanline is the real default)
654 Even scanlines are from CGA_base + 0x0000, odd from CGA_base + 0x2000
655 ***************************************************************************/
656
MC6845_UPDATE_ROW(isa8_cga_device::cga_gfx_1bpp_update_row)657 MC6845_UPDATE_ROW( isa8_cga_device::cga_gfx_1bpp_update_row )
658 {
659 uint8_t const *const videoram = &m_vram[m_start_offset];
660 uint32_t *p = &bitmap.pix(y);
661 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
662 uint8_t const fg = m_color_select & 0x0f;
663
664 if (y == 0) CGA_LOG(1,"cga_gfx_1bpp_update_row",("\n"));
665 for (int i = 0; i < x_count; i++)
666 {
667 uint16_t const offset = (((ma + i) << 1) & 0x1fff) | ((ra & 1) << 13);
668 uint8_t data;
669
670 data = videoram[offset];
671
672 *p++ = palette[(data & 0x80) ? fg : 0];
673 *p++ = palette[(data & 0x40) ? fg : 0];
674 *p++ = palette[(data & 0x20) ? fg : 0];
675 *p++ = palette[(data & 0x10) ? fg : 0];
676 *p++ = palette[(data & 0x08) ? fg : 0];
677 *p++ = palette[(data & 0x04) ? fg : 0];
678 *p++ = palette[(data & 0x02) ? fg : 0];
679 *p++ = palette[(data & 0x01) ? fg : 0];
680
681 data = videoram[offset + 1];
682
683 *p++ = palette[(data & 0x80) ? fg : 0];
684 *p++ = palette[(data & 0x40) ? fg : 0];
685 *p++ = palette[(data & 0x20) ? fg : 0];
686 *p++ = palette[(data & 0x10) ? fg : 0];
687 *p++ = palette[(data & 0x08) ? fg : 0];
688 *p++ = palette[(data & 0x04) ? fg : 0];
689 *p++ = palette[(data & 0x02) ? fg : 0];
690 *p++ = palette[(data & 0x01) ? fg : 0];
691 }
692 }
693
694
WRITE_LINE_MEMBER(isa8_cga_device::hsync_changed)695 WRITE_LINE_MEMBER( isa8_cga_device::hsync_changed )
696 {
697 m_hsync = state ? 1 : 0;
698 if(state && !m_vsync)
699 {
700 m_screen->update_now();
701 m_y++;
702 }
703 }
704
705
WRITE_LINE_MEMBER(isa8_cga_device::vsync_changed)706 WRITE_LINE_MEMBER( isa8_cga_device::vsync_changed )
707 {
708 if ( state )
709 {
710 m_framecnt++;
711 }
712 else
713 {
714 m_screen->reset_origin();
715 m_y = 0;
716 }
717 m_vsync = state ? 9 : 0;
718 }
719
MC6845_RECONFIGURE(isa8_cga_device::reconfigure)720 MC6845_RECONFIGURE( isa8_cga_device::reconfigure )
721 {
722 rectangle curvisarea = m_screen->visible_area();
723 m_screen->set_visible_area(visarea.min_x, visarea.max_x, curvisarea.min_y, curvisarea.max_y);
724 }
725
set_palette_luts(void)726 void isa8_cga_device::set_palette_luts(void)
727 {
728 /* Setup 2bpp palette lookup table */
729 if ( m_mode_control & 0x10 )
730 {
731 m_palette_lut_2bpp[0] = 0;
732 }
733 else
734 {
735 m_palette_lut_2bpp[0] = m_color_select & 0x0F;
736 }
737 if ( m_mode_control & 0x04 )
738 {
739 m_palette_lut_2bpp[1] = ( ( m_color_select & 0x10 ) >> 1 ) | 3;
740 m_palette_lut_2bpp[2] = ( ( m_color_select & 0x10 ) >> 1 ) | 4;
741 m_palette_lut_2bpp[3] = ( ( m_color_select & 0x10 ) >> 1 ) | 7;
742 }
743 else
744 {
745 if ( m_color_select & 0x20 )
746 {
747 m_palette_lut_2bpp[1] = ( ( m_color_select & 0x10 ) >> 1 ) | 3;
748 m_palette_lut_2bpp[2] = ( ( m_color_select & 0x10 ) >> 1 ) | 5;
749 m_palette_lut_2bpp[3] = ( ( m_color_select & 0x10 ) >> 1 ) | 7;
750 }
751 else
752 {
753 m_palette_lut_2bpp[1] = ( ( m_color_select & 0x10 ) >> 1 ) | 2;
754 m_palette_lut_2bpp[2] = ( ( m_color_select & 0x10 ) >> 1 ) | 4;
755 m_palette_lut_2bpp[3] = ( ( m_color_select & 0x10 ) >> 1 ) | 6;
756 }
757 }
758 //logerror("2bpp lut set to %d,%d,%d,%d\n", cga.palette_lut_2bpp[0], cga.palette_lut_2bpp[1], cga.palette_lut_2bpp[2], cga.palette_lut_2bpp[3]);
759 }
760
761 /*
762 * rW CGA mode control register (see #P138)
763 *
764 * x x x 0 1 0 0 0 - 320x200, 40x25 text. Colour on RGB and composite monitors.
765 * x x x 0 1 0 0 1 - 640x200, 80x25 text. Colour on RGB and composite monitors.
766 * x x x 0 1 0 1 0 - 320x200 graphics. Colour on RGB and composite monitors.
767 * x x x 0 1 0 1 1 - unknown/invalid.
768 * x x x 0 1 1 0 0 - 320x200, 40x25 text. Colour on RGB, greyscale on composite monitors.
769 * x x x 0 1 1 0 1 - 640x200, 80x25 text. Colour on RGB, greyscale on composite monitors.
770 * x x x 0 1 1 1 0 - 320x200 graphics. Alternative palette on RGB, greyscale on composite monitors.
771 * x x x 0 1 1 1 1 - unknown/invalid.
772 * x x x 1 1 0 0 0 - unknown/invalid.
773 * x x x 1 1 0 0 1 - unknown/invalid.
774 * x x x 1 1 0 1 0 - 160x200/640x200 graphics. 640x200 ?? on RGB monitor, 160x200 on composite monitor.
775 * x x x 1 1 0 1 1 - unknown/invalid.
776 * x x x 1 1 1 0 0 - unknown/invalid.
777 * x x x 1 1 1 0 1 - unknown/invalid.
778 * x x x 1 1 1 1 0 - 640x200 graphics. Colour on black on RGB monitor, monochrome on composite monitor.
779 * x x x 1 1 1 1 1 - unknown/invalid.
780 */
mode_control_w(uint8_t data)781 void isa8_cga_device::mode_control_w(uint8_t data)
782 {
783 uint8_t monitor = CGA_MONITOR;
784
785 m_mode_control = data;
786
787 //logerror("mode set to %02X\n", cga.mode_control & 0x3F );
788 switch ( m_mode_control & 0x3F )
789 {
790 case 0x08: case 0x09: case 0x0C: case 0x0D:
791 m_crtc->set_hpixels_per_column( 8 );
792 if ( monitor == CGA_MONITOR_COMPOSITE )
793 {
794 if ( m_mode_control & 0x04 )
795 {
796 /* Composite greyscale */
797 m_update_row_type = CGA_TEXT_INTEN_CG;
798 }
799 else
800 {
801 /* Composite colour */
802 m_update_row_type = CGA_TEXT_INTEN;
803 }
804 }
805 else
806 {
807 /* RGB colour */
808 m_update_row_type = CGA_TEXT_INTEN;
809 }
810 break;
811 case 0x0A: case 0x0B: case 0x2A: case 0x2B:
812 m_crtc->set_hpixels_per_column( 8 );
813 if ( monitor == CGA_MONITOR_COMPOSITE )
814 {
815 m_update_row_type = CGA_GFX_4BPPL;
816 }
817 else
818 {
819 m_update_row_type = CGA_GFX_2BPP;
820 }
821 break;
822 case 0x0E: case 0x0F: case 0x2E: case 0x2F:
823 m_crtc->set_hpixels_per_column( 8 );
824 m_update_row_type = CGA_GFX_2BPP;
825 break;
826 case 0x18: case 0x19: case 0x1C: case 0x1D:
827 m_crtc->set_hpixels_per_column( 8 );
828 m_update_row_type = CGA_TEXT_INTEN_ALT;
829 break;
830 case 0x1A: case 0x1B: case 0x3A: case 0x3B:
831 m_crtc->set_hpixels_per_column( 16 );
832 if ( monitor == CGA_MONITOR_COMPOSITE )
833 {
834 m_update_row_type = CGA_GFX_4BPPH;
835 }
836 else
837 {
838 m_update_row_type = CGA_GFX_1BPP;
839 }
840 break;
841 case 0x1E: case 0x1F: case 0x3E: case 0x3F:
842 m_crtc->set_hpixels_per_column( 16 );
843 m_update_row_type = CGA_GFX_1BPP;
844 break;
845 case 0x28: case 0x29: case 0x2C: case 0x2D:
846 m_crtc->set_hpixels_per_column( 8 );
847 if ( monitor == CGA_MONITOR_COMPOSITE )
848 {
849 if ( m_mode_control & 0x04 )
850 {
851 /* Composite greyscale */
852 m_update_row_type = m_superimpose ? CGA_TEXT_BLINK_SI : CGA_TEXT_BLINK;
853 }
854 else
855 {
856 /* Composite colour */
857 m_update_row_type = m_superimpose ? CGA_TEXT_BLINK_SI : CGA_TEXT_BLINK;
858 }
859 }
860 else
861 {
862 /* RGB colour */
863 m_update_row_type = m_superimpose ? CGA_TEXT_BLINK_SI : CGA_TEXT_BLINK;
864 }
865 break;
866 case 0x38: case 0x39: case 0x3C: case 0x3D:
867 m_crtc->set_hpixels_per_column( 8 );
868 m_update_row_type = CGA_TEXT_BLINK_ALT;
869 break;
870 default:
871 m_update_row_type = -1;
872 break;
873 }
874
875 // The lowest bit of the mode register selects, among others, the
876 // input clock to the 6845.
877 m_crtc->set_unscaled_clock( ( m_mode_control & 1 ) ? CGA_HCLK : CGA_LCLK );
878
879 set_palette_luts();
880 }
881
882
883
884 /*
885 * Select Plantronics modes
886 */
plantronics_w(uint8_t data)887 void isa8_cga_device::plantronics_w(uint8_t data)
888 {
889 if ( ( CGA_CHIPSET ) != CGA_CHIPSET_ATI) return;
890
891 data &= 0x70; /* Only bits 6-4 are used */
892 m_plantronics = data;
893 }
894
895
896
897 /*************************************************************************
898 *
899 * CGA
900 * color graphics adapter
901 *
902 *************************************************************************/
903
904
io_read(offs_t offset)905 uint8_t isa8_cga_device::io_read(offs_t offset)
906 {
907 uint8_t data = 0xff;
908
909 switch( offset )
910 {
911 case 0: case 2: case 4: case 6:
912 /* return last written mc6845 address value here? */
913 break;
914 case 1: case 3: case 5: case 7:
915 data = m_crtc->register_r();
916 break;
917 case 10:
918 data = m_vsync | ( ( data & 0x40 ) >> 4 ) | m_hsync;
919 break;
920 }
921 return data;
922 }
923
924
925
io_write(offs_t offset,uint8_t data)926 void isa8_cga_device::io_write(offs_t offset, uint8_t data)
927 {
928 switch(offset) {
929 case 0: case 2: case 4: case 6:
930 m_crtc->address_w(data);
931 break;
932 case 1: case 3: case 5: case 7:
933 m_crtc->register_w(data);
934 break;
935 case 8:
936 mode_control_w(data);
937 break;
938 case 9:
939 m_color_select = data;
940 set_palette_luts();
941 break;
942 case 0x0d:
943 plantronics_w(data);
944 break;
945 }
946 }
947
948
949
950 /* Old plantronics rendering code, leaving it uncommented until we have re-implemented it */
951
952 //
953 // From choosevideomode:
954 //
955 // /* Plantronics high-res */
956 // if ((cga.mode_control & 2) && (cga.plantronics & 0x20))
957 // proc = cga_pgfx_2bpp;
958 // /* Plantronics low-res */
959 // if ((cga.mode_control & 2) && (cga.plantronics & 0x10))
960 // proc = cga_pgfx_4bpp;
961 //
962
963 #if 0
964 static inline void pgfx_plot_unit_4bpp(bitmap_ind16 &bitmap, int x, int y, int offs)
965 {
966 int values[2];
967
968 if (cga.plantronics & 0x40)
969 {
970 values[0] = videoram[offs | 0x4000];
971 values[1] = videoram[offs];
972 }
973 else
974 {
975 values[0] = videoram[offs];
976 values[1] = videoram[offs | 0x4000];
977 }
978 for (int i = 3; i >= 0; i--)
979 {
980 int const color =
981 ((values[0] & 0x3) << 1) |
982 ((values[1] & 2) >> 1) |
983 ((values[1] & 1) << 3);
984 bitmap.pix(y, x + i) = Machine->pens[color];
985 values[0] >>= 2;
986 values[1] >>= 2;
987 }
988 }
989 #endif
990
991
992 ///***************************************************************************
993 // Draw graphics mode with 640x200 pixels (default) with 2 bits/pixel.
994 // Even scanlines are from CGA_base + 0x0000, odd from CGA_base + 0x2000
995 // Second plane at CGA_base + 0x4000 / 0x6000
996 //****************************************************************************
997
998 #if 0
999 static void cga_pgfx_4bpp(bitmap_ind16 &bitmap, struct mscrtc6845 *crtc)
1000 {
1001 int offs = mscrtc6845_get_start(crtc) * 2;
1002 int const lines = mscrtc6845_get_char_lines(crtc);
1003 int const height = mscrtc6845_get_char_height(crtc);
1004 int columns = mscrtc6845_get_char_columns(crtc) * 2;
1005
1006 for (int sy = 0; sy < lines; sy++, offs = (offs + columns) & 0x1fff)
1007 {
1008 for (int sh = 0; sh < height; sh++, offs |= 0x2000)
1009 {
1010 // char line 0 used as a12 line in graphic mode
1011 if (!(sh & 1))
1012 {
1013 for (int i = offs, sx = 0; sx < columns; sx++, i = (i + 1) & 0x1fff)
1014 {
1015 pgfx_plot_unit_4bpp(bitmap, sx * 4, sy * height + sh, i);
1016 }
1017 }
1018 else
1019 {
1020 for (int i = offs | 0x2000, sx = 0; sx < columns; sx++, i = ((i + 1) & 0x1fff) | 0x2000)
1021 {
1022 pgfx_plot_unit_4bpp(bitmap, sx * 4, sy * height + sh, i);
1023 }
1024 }
1025 }
1026 }
1027 }
1028 #endif
1029
1030
1031 #if 0
1032 static inline void pgfx_plot_unit_2bpp(bitmap_ind16 &bitmap, int x, int y, const uint16_t *palette, int offs)
1033 {
1034 uint8_t values[2];
1035 if (cga.plantronics & 0x40)
1036 {
1037 values[0] = videoram[offs];
1038 values[1] = videoram[offs | 0x4000];
1039 }
1040 else
1041 {
1042 values[0] = videoram[offs | 0x4000];
1043 values[1] = videoram[offs];
1044 }
1045 uint8_t bmap[2] = { 0, 0 };
1046 for (int i = 3; i >= 0; i--)
1047 {
1048 bmap[0] = (bmap[0] << 1) | BIT(values[0], 7);
1049 bmap[0] = (bmap[0] << 1) | BIT(values[1], 7);
1050 bmap[1] = (bmap[1] << 1) | BIT(values[0], 3);
1051 bmap[1] = (bmap[1] << 1) | BIT(values[1], 3);
1052 values[0] <<= 1;
1053 values[1] <<= 1;
1054 }
1055
1056 uint16_t *dest = &bitmap.pix(y, x);
1057 *dest++ = palette[(bmap[0] >> 6) & 0x03];
1058 *dest++ = palette[(bmap[0] >> 4) & 0x03];
1059 *dest++ = palette[(bmap[0] >> 2) & 0x03];
1060 *dest++ = palette[(bmap[0] >> 0) & 0x03];
1061 *dest++ = palette[(bmap[1] >> 6) & 0x03];
1062 *dest++ = palette[(bmap[1] >> 4) & 0x03];
1063 *dest++ = palette[(bmap[1] >> 2) & 0x03];
1064 *dest++ = palette[(bmap[1] >> 0) & 0x03];
1065 }
1066 #endif
1067
1068
1069 ///***************************************************************************
1070 // Draw graphics mode with 320x200 pixels (default) with 2 bits/pixel.
1071 // Even scanlines are from CGA_base + 0x0000, odd from CGA_base + 0x2000
1072 // cga fetches 2 byte per mscrtc6845 access (not modeled here)!
1073 //****************************************************************************
1074
1075 #if 0
1076 static void cga_pgfx_2bpp(bitmap_ind16 &bitmap, struct mscrtc6845 *crtc)
1077 {
1078 int offs = mscrtc6845_get_start(crtc) * 2;
1079 int const lines = mscrtc6845_get_char_lines(crtc);
1080 int const height = mscrtc6845_get_char_height(crtc);
1081 int const columns = mscrtc6845_get_char_columns(crtc) * 2;
1082
1083 /* Most chipsets use bit 2 of the mode control register to access a third palette. But not consistently. */
1084 int colorset = cga.color_select & 0x3f;
1085 pc_cga_check_palette();
1086 switch (CGA_CHIPSET)
1087 {
1088 /* The IBM Professional Graphics Controller behaves like the PC1512, btw. */
1089 case CGA_CHIPSET_PC1512:
1090 if ((colorset < 32) && (cga.mode_control & 4)) colorset += 64;
1091 break;
1092
1093 case CGA_CHIPSET_IBM:
1094 case CGA_CHIPSET_PC200:
1095 case CGA_CHIPSET_ATI:
1096 case CGA_CHIPSET_PARADISE:
1097 if (cga.mode_control & 4) colorset = (colorset & 0x1f) + 64;
1098 break;
1099 }
1100
1101 /* The fact that our palette is located in cga_colortable is a vestigial
1102 * aspect from when we were doing that ugly trick where drawgfx() would
1103 * handle graphics drawing. Truthfully, we should probably be using
1104 * palette_set_color_rgb() here and not doing the palette lookup in the loop
1105 */
1106 uint16_t const *const palette = &cga_colortable[256*2 + 16*2] + colorset * 4;
1107
1108 for (int sy = 0; sy < lines; sy++, offs = (offs + columns) & 0x1fff)
1109 {
1110
1111 for (int sh = 0; sh < height; sh++)
1112 {
1113 if (!(sh & 1)) // char line 0 used as a12 line in graphic mode
1114 {
1115 for (int i = offs, sx = 0; sx < columns; sx++, i = (i + 1) & 0x1fff)
1116 {
1117 pgfx_plot_unit_2bpp(bitmap, sx * 8, sy * height + sh, palette, i);
1118 }
1119 }
1120 else
1121 {
1122 for (int i = offs | 0x2000, sx = 0; sx < columns; sx++, i= ((i + 1) & 0x1fff) | 0x2000)
1123 {
1124 pgfx_plot_unit_2bpp(bitmap, sx * 8, sy * height + sh, palette, i);
1125 }
1126 }
1127 }
1128 }
1129 }
1130 #endif
1131
1132
MC6845_UPDATE_ROW(isa8_cga_pc1512_device::pc1512_gfx_4bpp_update_row)1133 MC6845_UPDATE_ROW( isa8_cga_pc1512_device::pc1512_gfx_4bpp_update_row )
1134 {
1135 uint8_t const *const videoram = &m_vram[m_start_offset];
1136 uint32_t *p = &bitmap.pix(y);
1137 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
1138 uint16_t const offset_base = ra << 13;
1139
1140 if (y == 0) CGA_LOG(1,"pc1512_gfx_4bpp_update_row",("\n"));
1141 for (int j = 0; j < x_count; j++)
1142 {
1143 uint16_t const offset = offset_base | ((ma + j) & 0x1fff);
1144 uint16_t const i = (m_color_select & 8) ? videoram[isa8_cga_pc1512_device::vram_offset[3] | offset] << 3 : 0;
1145 uint16_t const r = (m_color_select & 4) ? videoram[isa8_cga_pc1512_device::vram_offset[2] | offset] << 2 : 0;
1146 uint16_t const g = (m_color_select & 2) ? videoram[isa8_cga_pc1512_device::vram_offset[1] | offset] << 1 : 0;
1147 uint16_t const b = (m_color_select & 1) ? videoram[isa8_cga_pc1512_device::vram_offset[0] | offset] : 0;
1148
1149 *p++ = palette[((i & 0x400) | (r & 0x200) | (g & 0x100) | (b & 0x80) ) >> 7];
1150 *p++ = palette[((i & 0x200) | (r & 0x100) | (g & 0x080) | (b & 0x40) ) >> 6];
1151 *p++ = palette[((i & 0x100) | (r & 0x080) | (g & 0x040) | (b & 0x20) ) >> 5];
1152 *p++ = palette[((i & 0x080) | (r & 0x040) | (g & 0x020) | (b & 0x10) ) >> 4];
1153 *p++ = palette[((i & 0x040) | (r & 0x020) | (g & 0x010) | (b & 0x08) ) >> 3];
1154 *p++ = palette[((i & 0x020) | (r & 0x010) | (g & 0x008) | (b & 0x04) ) >> 2];
1155 *p++ = palette[((i & 0x010) | (r & 0x008) | (g & 0x004) | (b & 0x02) ) >> 1];
1156 *p++ = palette[ (i & 0x008) | (r & 0x004) | (g & 0x002) | (b & 0x01) ];
1157 }
1158 }
1159
1160
io_write(offs_t offset,uint8_t data)1161 void isa8_cga_pc1512_device::io_write(offs_t offset, uint8_t data)
1162 {
1163 switch (offset)
1164 {
1165 case 0: case 2: case 4: case 6:
1166 data &= 0x1F;
1167 m_crtc->address_w(data);
1168 m_mc6845_address = data;
1169 break;
1170
1171 case 1: case 3: case 5: case 7:
1172 if ( ! m_mc6845_locked_register[m_mc6845_address] )
1173 {
1174 m_crtc->register_w(data);
1175 if ( isa8_cga_pc1512_device::mc6845_writeonce_register[m_mc6845_address] )
1176 {
1177 m_mc6845_locked_register[m_mc6845_address] = 1;
1178 }
1179 }
1180 break;
1181
1182 case 0x8:
1183 /* Check if we're changing to graphics mode 2 */
1184 if ( ( m_mode_control & 0x12 ) != 0x12 && ( data & 0x12 ) == 0x12 )
1185 {
1186 m_write = 0x0F;
1187 }
1188 else
1189 {
1190 membank("bank1")->set_base(&m_vram[isa8_cga_pc1512_device::vram_offset[0]]);
1191 }
1192 m_mode_control = data;
1193 switch( m_mode_control & 0x3F )
1194 {
1195 case 0x08: case 0x09: case 0x0C: case 0x0D:
1196 m_crtc->set_hpixels_per_column( 8 );
1197 m_update_row_type = CGA_TEXT_INTEN;
1198 break;
1199 case 0x0A: case 0x0B: case 0x2A: case 0x2B:
1200 m_crtc->set_hpixels_per_column( 8 );
1201 if ( ( CGA_MONITOR ) == CGA_MONITOR_COMPOSITE )
1202 {
1203 m_update_row_type = CGA_GFX_4BPPL;
1204 }
1205 else
1206 {
1207 m_update_row_type = CGA_GFX_2BPP;
1208 }
1209 break;
1210 case 0x0E: case 0x0F: case 0x2E: case 0x2F:
1211 m_crtc->set_hpixels_per_column( 8 );
1212 m_update_row_type = CGA_GFX_2BPP;
1213 break;
1214 case 0x18: case 0x19: case 0x1C: case 0x1D:
1215 m_crtc->set_hpixels_per_column( 8 );
1216 m_update_row_type = CGA_TEXT_INTEN_ALT;
1217 break;
1218 case 0x1A: case 0x1B: case 0x3A: case 0x3B:
1219 m_crtc->set_hpixels_per_column( 8 );
1220 m_update_row_type = PC1512_GFX_4BPP;
1221 break;
1222 case 0x1E: case 0x1F: case 0x3E: case 0x3F:
1223 m_crtc->set_hpixels_per_column( 16 );
1224 m_update_row_type = CGA_GFX_1BPP;
1225 break;
1226 case 0x28: case 0x29: case 0x2C: case 0x2D:
1227 m_crtc->set_hpixels_per_column( 8 );
1228 m_update_row_type = CGA_TEXT_BLINK;
1229 break;
1230 case 0x38: case 0x39: case 0x3C: case 0x3D:
1231 m_crtc->set_hpixels_per_column( 8 );
1232 m_update_row_type = CGA_TEXT_BLINK_ALT;
1233 break;
1234 default:
1235 m_update_row_type = -1;
1236 break;
1237 }
1238 break;
1239
1240 case 0xd:
1241 m_write = data;
1242 break;
1243
1244 case 0xe:
1245 m_read = data;
1246 if ( ( m_mode_control & 0x12 ) == 0x12 )
1247 {
1248 membank("bank1")->set_base(&m_vram[isa8_cga_pc1512_device::vram_offset[data & 3]]);
1249 }
1250 break;
1251
1252 default:
1253 isa8_cga_device::io_write(offset, data);
1254 break;
1255 }
1256 }
1257
1258
io_read(offs_t offset)1259 uint8_t isa8_cga_pc1512_device::io_read(offs_t offset)
1260 {
1261 uint8_t data;
1262
1263 switch (offset)
1264 {
1265 case 0xd:
1266 data = m_write;
1267 break;
1268
1269 case 0xe:
1270 data = m_read;
1271 break;
1272
1273 default:
1274 data = isa8_cga_device::io_read(offset);
1275 break;
1276 }
1277 return data;
1278 }
1279
1280
vram_w(offs_t offset,uint8_t data)1281 void isa8_cga_pc1512_device::vram_w(offs_t offset, uint8_t data)
1282 {
1283 if ( ( m_mode_control & 0x12 ) == 0x12 )
1284 {
1285 if (m_write & 1)
1286 m_vram[offset+isa8_cga_pc1512_device::vram_offset[0]] = data; /* blue plane */
1287 if (m_write & 2)
1288 m_vram[offset+isa8_cga_pc1512_device::vram_offset[1]] = data; /* green */
1289 if (m_write & 4)
1290 m_vram[offset+isa8_cga_pc1512_device::vram_offset[2]] = data; /* red */
1291 if (m_write & 8)
1292 m_vram[offset+isa8_cga_pc1512_device::vram_offset[3]] = data; /* intensity (text, 4color) */
1293 }
1294 else
1295 {
1296 m_vram[offset + isa8_cga_pc1512_device::vram_offset[0]] = data;
1297 }
1298 }
1299
1300
1301 DEFINE_DEVICE_TYPE(ISA8_CGA_PC1512, isa8_cga_pc1512_device, "cga_pc1512", "ISA8_CGA_PC1512")
1302
1303 const offs_t isa8_cga_pc1512_device::vram_offset[4]= { 0x0000, 0x4000, 0x8000, 0xC000 };
1304 const uint8_t isa8_cga_pc1512_device::mc6845_writeonce_register[31] =
1305 {
1306 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1307 };
1308
1309 //-------------------------------------------------
1310 // isa8_cga_pc1512_device - constructor
1311 //-------------------------------------------------
1312
isa8_cga_pc1512_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1313 isa8_cga_pc1512_device::isa8_cga_pc1512_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1314 isa8_cga_device(mconfig, ISA8_CGA_PC1512, tag, owner, clock), m_write(0), m_read(0), m_mc6845_address(0)
1315 {
1316 m_vram_size = 0x10000;
1317 m_chr_gen_offset[0] = 0x0000;
1318 m_chr_gen_offset[1] = 0x0800;
1319 m_chr_gen_offset[2] = 0x1000;
1320 m_chr_gen_offset[3] = 0x1800;
1321 }
1322
1323
device_rom_region() const1324 const tiny_rom_entry *isa8_cga_pc1512_device::device_rom_region() const
1325 {
1326 return nullptr;
1327 }
1328
1329
device_input_ports() const1330 ioport_constructor isa8_cga_pc1512_device::device_input_ports() const
1331 {
1332 return INPUT_PORTS_NAME( pc1512 );
1333 }
1334
1335 //-------------------------------------------------
1336 // device_start - device-specific startup
1337 //-------------------------------------------------
1338
device_start()1339 void isa8_cga_pc1512_device::device_start()
1340 {
1341 isa8_cga_device::device_start();
1342
1343 m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*this, FUNC(isa8_cga_pc1512_device::io_read)), write8sm_delegate(*this, FUNC(isa8_cga_pc1512_device::io_write)));
1344 m_isa->install_bank(0xb8000, 0xbbfff, "bank1", &m_vram[0]);
1345
1346 address_space &space = m_isa->memspace();
1347
1348 space.install_write_handler(0xb8000, 0xbbfff, write8sm_delegate(*this, FUNC(isa8_cga_pc1512_device::vram_w)));
1349 space.install_write_handler(0xbc000, 0xbffff, write8sm_delegate(*this, FUNC(isa8_cga_pc1512_device::vram_w)));
1350 }
1351
device_reset()1352 void isa8_cga_pc1512_device::device_reset()
1353 {
1354 isa8_cga_device::device_reset();
1355
1356 m_write = 0x0f;
1357 m_read = 0;
1358 m_mc6845_address = 0;
1359 for (auto & elem : m_mc6845_locked_register)
1360 {
1361 elem = 0;
1362 }
1363
1364 membank("bank1")->set_base(&m_vram[isa8_cga_pc1512_device::vram_offset[0]]);
1365 }
1366
change_resolution(uint8_t mode)1367 void isa8_wyse700_device::change_resolution(uint8_t mode)
1368 {
1369 int width = 0, height = 0;
1370 if (mode & 2) {
1371 machine().root_device().membank("bank_wy1")->set_base(&m_vram[0x10000]);
1372 } else {
1373 machine().root_device().membank("bank_wy1")->set_base(&m_vram[0x00000]);
1374 }
1375 if ((m_control & 0xf0) == (mode & 0xf0)) return;
1376
1377 switch(mode & 0xf0) {
1378 case 0xc0: width = 1280; height = 800; break;
1379 case 0xa0: width = 1280; height = 400; break;
1380 case 0x80: width = 640; height = 400; break;
1381 case 0x00: width = 640; height = 400; break; // unhandled
1382 }
1383 rectangle visarea(0, width-1, 0, height-1);
1384 m_screen->configure(width, height, visarea, HZ_TO_ATTOSECONDS(60));
1385
1386 }
1387
io_write(offs_t offset,uint8_t data)1388 void isa8_wyse700_device::io_write(offs_t offset, uint8_t data)
1389 {
1390 switch (offset)
1391 {
1392 case 0xd:
1393 m_bank_offset = data;
1394 break;
1395
1396 case 0xe:
1397 m_bank_base = data;
1398 break;
1399
1400 case 0xf:
1401 change_resolution(data);
1402 m_control = data;
1403 break;
1404 default:
1405 isa8_cga_device::io_write(offset, data);
1406 break;
1407 }
1408 }
1409
1410
io_read(offs_t offset)1411 uint8_t isa8_wyse700_device::io_read(offs_t offset)
1412 {
1413 uint8_t data;
1414
1415 switch (offset)
1416 {
1417 case 0xd:
1418 data = m_bank_offset;
1419 break;
1420
1421 case 0xe:
1422 data = m_bank_base;
1423 break;
1424
1425 case 0xf:
1426 data = m_control;
1427 break;
1428 default:
1429 data = isa8_cga_device::io_read(offset);
1430 break;
1431 }
1432 return data;
1433 }
1434
1435
1436 DEFINE_DEVICE_TYPE(ISA8_WYSE700, isa8_wyse700_device, "wyse700", "Wyse 700")
1437
1438
1439 //-------------------------------------------------
1440 // isa8_wyse700_device - constructor
1441 //-------------------------------------------------
1442
isa8_wyse700_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1443 isa8_wyse700_device::isa8_wyse700_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1444 isa8_cga_device(mconfig, ISA8_WYSE700, tag, owner, clock), m_bank_offset(0), m_bank_base(0), m_control(0)
1445 {
1446 m_vram_size = 0x20000;
1447 m_start_offset = 0x18000;
1448 }
1449
1450 /*
1451 Character ROMs:
1452
1453 250211-03.e5: Character ROM Label: "(C) WYSE TECH / REV.A / 250211-03"
1454 250212-03.f5: Character ROM Label: "(C) WYSE TECH / REV.A / 250212-03"
1455
1456 Not dumped:
1457
1458 250026-03.2d: MC68705 MCU Label: "(C) WYSE TECH / REV.1 / 250026-03"
1459 250270-01.8b: PAL? Label: "250270-01"
1460 250024-01.8g: PAL? Label: "250024-01"
1461 250210-01.c2: PAL? Label: "250210-01"
1462 */
1463 ROM_START( wyse700 )
1464 ROM_REGION(0x4000,"gfx1", 0)
1465 ROM_LOAD( "250211-03.e5", 0x0000, 0x2000, CRC(58b61f63) SHA1(29ecb7cf7d07d692f0fc54e2dea8389f17a65f1a))
1466 ROM_LOAD( "250212-03.f5", 0x2000, 0x2000, CRC(6930d741) SHA1(1beeb133c5e39eee9914bdc5924039d70b5edcad))
1467 ROM_END
1468
device_rom_region() const1469 const tiny_rom_entry *isa8_wyse700_device::device_rom_region() const
1470 {
1471 return ROM_NAME( wyse700 );
1472 }
1473
1474 //-------------------------------------------------
1475 // device_start - device-specific startup
1476 //-------------------------------------------------
1477
device_start()1478 void isa8_wyse700_device::device_start()
1479 {
1480 isa8_cga_device::device_start();
1481
1482 m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*this, FUNC(isa8_wyse700_device::io_read)), write8sm_delegate(*this, FUNC(isa8_wyse700_device::io_write)));
1483 m_isa->install_bank(0xa0000, 0xaffff, "bank_wy1", &m_vram[0x00000]);
1484 m_isa->install_bank(0xb0000, 0xbffff, "bank_cga", &m_vram[0x10000]);
1485 }
1486
device_reset()1487 void isa8_wyse700_device::device_reset()
1488 {
1489 isa8_cga_device::device_reset();
1490 m_control = 0;
1491 m_bank_offset = 0;
1492 m_bank_base = 0;
1493 }
1494
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)1495 uint32_t isa8_wyse700_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
1496 {
1497 if (m_control & 0x08)
1498 {
1499 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
1500 uint8_t const fg = m_color_select & 0x0F;
1501 uint32_t addr = 0;
1502 for (int y = 0; y < 800; y++)
1503 {
1504 uint8_t const *src = &m_vram[addr];
1505
1506 if (y & 1)
1507 {
1508 src += 0x10000;
1509 addr += 160;
1510 }
1511
1512 for (int x = 0; x < (1280 / 8); x++)
1513 {
1514 uint8_t val = src[x];
1515
1516 for (int i = 0; i < 8; i++)
1517 {
1518 bitmap.pix(y, x * 8 + i) = (val & 0x80) ? palette[fg] : palette[0x00];
1519 val <<= 1;
1520 }
1521 }
1522 }
1523 return 0;
1524 }
1525 else
1526 {
1527 return isa8_cga_device::screen_update(screen, bitmap, cliprect);
1528 }
1529 }
1530
1531
1532 DEFINE_DEVICE_TYPE(ISA8_EC1841_0002, isa8_ec1841_0002_device, "ec1841_0002", "EC 1841.0002 (CGA)")
1533
1534 //-------------------------------------------------
1535 // isa8_ec1841_0002_device - constructor
1536 //-------------------------------------------------
1537
isa8_ec1841_0002_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1538 isa8_ec1841_0002_device::isa8_ec1841_0002_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1539 isa8_cga_device(mconfig, ISA8_EC1841_0002, tag, owner, clock), m_p3df(0)
1540 {
1541 }
1542
1543 //-------------------------------------------------
1544 // device_start - device-specific startup
1545 //-------------------------------------------------
1546
device_start()1547 void isa8_ec1841_0002_device::device_start()
1548 {
1549 isa8_cga_device::device_start();
1550
1551 m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*this, FUNC(isa8_ec1841_0002_device::io_read)), write8sm_delegate(*this, FUNC(isa8_ec1841_0002_device::io_write)));
1552 }
1553
device_reset()1554 void isa8_ec1841_0002_device::device_reset()
1555 {
1556 isa8_cga_device::device_reset();
1557 m_p3df = 0;
1558 }
1559
char_ram_write(offs_t offset,uint8_t data)1560 void isa8_ec1841_0002_device::char_ram_write(offs_t offset, uint8_t data)
1561 {
1562 offset ^= BIT(offset, 12);
1563 // logerror("write char ram %04x %02x\n",offset,data);
1564 m_chr_gen_base[offset + 0x0000] = data;
1565 m_chr_gen_base[offset + 0x0800] = data;
1566 m_chr_gen_base[offset + 0x1000] = data;
1567 m_chr_gen_base[offset + 0x1800] = data;
1568 }
1569
char_ram_read(offs_t offset)1570 uint8_t isa8_ec1841_0002_device::char_ram_read(offs_t offset)
1571 {
1572 offset ^= BIT(offset, 12);
1573 return m_chr_gen_base[offset];
1574 }
1575
io_write(offs_t offset,uint8_t data)1576 void isa8_ec1841_0002_device::io_write(offs_t offset, uint8_t data)
1577 {
1578 switch (offset)
1579 {
1580 case 0x0f:
1581 m_p3df = data;
1582 if (data & 1) {
1583 m_isa->install_memory(0xb8000, 0xb9fff,
1584 read8sm_delegate( *this, FUNC(isa8_ec1841_0002_device::char_ram_read)),
1585 write8sm_delegate(*this, FUNC(isa8_ec1841_0002_device::char_ram_write)));
1586 if(m_vram_size == 0x4000)
1587 m_isa->install_memory(0xbc000, 0xbdfff,
1588 read8sm_delegate( *this, FUNC(isa8_ec1841_0002_device::char_ram_read)),
1589 write8sm_delegate(*this, FUNC(isa8_ec1841_0002_device::char_ram_write)));
1590 } else {
1591 m_isa->install_bank(0xb8000, 0xb8000 + (std::min<size_t>)(0x8000, m_vram_size) - 1, "bank_cga", &m_vram[0]);
1592 if(m_vram_size == 0x4000)
1593 m_isa->install_bank(0xbc000, 0xbffff, "bank_cga", &m_vram[0]);
1594 }
1595 break;
1596 default:
1597 isa8_cga_device::io_write(offset, data);
1598 break;
1599 }
1600 }
1601
io_read(offs_t offset)1602 uint8_t isa8_ec1841_0002_device::io_read(offs_t offset)
1603 {
1604 uint8_t data;
1605
1606 switch (offset)
1607 {
1608 case 0x0f:
1609 data = m_p3df;
1610 break;
1611 default:
1612 data = isa8_cga_device::io_read(offset);
1613 break;
1614 }
1615 return data;
1616 }
1617
1618 DEFINE_DEVICE_TYPE(ISA8_CGA_MC1502, isa8_cga_mc1502_device, "cga_mc1502", "MC1502 CGA")
1619
device_add_mconfig(machine_config & config)1620 void isa8_cga_mc1502_device::device_add_mconfig(machine_config &config)
1621 {
1622 screen_device &screen(SCREEN(config, CGA_SCREEN_NAME, SCREEN_TYPE_RASTER));
1623 screen.set_raw(XTAL(16'000'000), 912, 0, 640, 462, 0, 400);
1624 screen.set_screen_update(FUNC(isa8_cga_mc1502_device::screen_update));
1625
1626 PALETTE(config, m_palette).set_entries(/* CGA_PALETTE_SETS * 16*/ 65536);
1627
1628 MC6845(config, m_crtc, XTAL(16'000'000)/16); // soviet clone
1629 m_crtc->set_screen(nullptr);
1630 m_crtc->set_show_border_area(false);
1631 m_crtc->set_char_width(8);
1632 m_crtc->set_update_row_callback(FUNC(isa8_cga_mc1502_device::crtc_update_row));
1633 m_crtc->out_hsync_callback().set(FUNC(isa8_cga_mc1502_device::hsync_changed));
1634 m_crtc->out_vsync_callback().set(FUNC(isa8_cga_mc1502_device::vsync_changed));
1635 m_crtc->set_reconfigure_callback(FUNC(isa8_cga_mc1502_device::reconfigure));
1636 }
1637
MC6845_RECONFIGURE(isa8_cga_mc1502_device::reconfigure)1638 MC6845_RECONFIGURE( isa8_cga_mc1502_device::reconfigure )
1639 {
1640 // this has a different horiz freq
1641 m_screen->configure(width, height, visarea, frame_period);
1642 }
1643
1644 //-------------------------------------------------
1645 // isa8_cga_mc1502_device - constructor
1646 //-------------------------------------------------
1647
isa8_cga_mc1502_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1648 isa8_cga_mc1502_device::isa8_cga_mc1502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1649 isa8_cga_device(mconfig, ISA8_CGA_MC1502, tag, owner, clock)
1650 {
1651 m_vram_size = 0x8000;
1652 m_chr_gen_offset[0] = 0x0000;
1653 m_chr_gen_offset[1] = 0x0800;
1654
1655 }
1656
1657 ROM_START( cga_iskr1031 )
1658 ROM_REGION(0x2000,"gfx1", 0)
CRC(f4d62e80)1659 ROM_LOAD( "iskra-1031_font.bin", 0x0000, 0x2000, CRC(f4d62e80) SHA1(ad7e81a0c9abc224671422bbcf6f6262da92b510))
1660 ROM_END
1661
1662 //-------------------------------------------------
1663 // rom_region - device-specific ROM region
1664 //-------------------------------------------------
1665
1666 const tiny_rom_entry *isa8_cga_iskr1031_device::device_rom_region() const
1667 {
1668 return ROM_NAME( cga_iskr1031 );
1669 }
1670
1671 DEFINE_DEVICE_TYPE(ISA8_CGA_ISKR1031, isa8_cga_iskr1031_device, "cga_iskr1031", "Iskra-1031 CGA")
1672
1673 //-------------------------------------------------
1674 // isa8_cga_iskr1031_device - constructor
1675 //-------------------------------------------------
1676
isa8_cga_iskr1031_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1677 isa8_cga_iskr1031_device::isa8_cga_iskr1031_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1678 isa8_cga_device(mconfig, ISA8_CGA_ISKR1031, tag, owner, clock)
1679 {
1680 }
1681
1682 ROM_START( cga_iskr1030m )
1683 ROM_REGION(0x2000,"gfx1", 0)
1684 ROM_LOAD( "iskra-1030m.chr", 0x0000, 0x2000, CRC(50b162eb) SHA1(5bd7cb1705a69bd16115a4c9ed1c2748a5c8ad51))
1685 ROM_END
1686
1687 //-------------------------------------------------
1688 // rom_region - device-specific ROM region
1689 //-------------------------------------------------
1690
device_rom_region() const1691 const tiny_rom_entry *isa8_cga_iskr1030m_device::device_rom_region() const
1692 {
1693 return ROM_NAME( cga_iskr1030m );
1694 }
1695
1696 DEFINE_DEVICE_TYPE(ISA8_CGA_ISKR1030M, isa8_cga_iskr1030m_device, "cga_iskr1030m", "Iskra-1030M CGA")
1697
1698 //-------------------------------------------------
1699 // isa8_cga_iskr1030m_device - constructor
1700 //-------------------------------------------------
1701
isa8_cga_iskr1030m_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1702 isa8_cga_iskr1030m_device::isa8_cga_iskr1030m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1703 isa8_cga_device(mconfig, ISA8_CGA_ISKR1030M, tag, owner, clock)
1704 {
1705 }
1706
1707 // XXX
1708
1709 ROM_START( mc1502 )
1710 ROM_REGION(0x2000,"gfx1", 0)
1711 // taken from mc1502
CRC(b2747a52)1712 ROM_LOAD( "symgen.rom", 0x0000, 0x2000, CRC(b2747a52) SHA1(6766d275467672436e91ac2997ac6b77700eba1e))
1713 ROM_END
1714
1715 const tiny_rom_entry *isa8_cga_mc1502_device::device_rom_region() const
1716 {
1717 return ROM_NAME( mc1502 );
1718 }
1719
1720 DEFINE_DEVICE_TYPE(ISA8_CGA_M24, isa8_cga_m24_device, "cga_m24", "Olivetti M24 CGA")
1721
device_add_mconfig(machine_config & config)1722 void isa8_cga_m24_device::device_add_mconfig(machine_config &config)
1723 {
1724 screen_device &screen(SCREEN(config, CGA_SCREEN_NAME, SCREEN_TYPE_RASTER));
1725 screen.set_raw(XTAL(14'318'181), 912, 0, 640, 462, 0, 400);
1726 screen.set_screen_update(FUNC(isa8_cga_m24_device::screen_update));
1727
1728 PALETTE(config, m_palette).set_entries(/* CGA_PALETTE_SETS * 16*/ 65536);
1729
1730 HD6845S(config, m_crtc, XTAL(14'318'181)/16);
1731 m_crtc->set_screen(nullptr);
1732 m_crtc->set_show_border_area(false);
1733 m_crtc->set_char_width(8);
1734 m_crtc->set_update_row_callback(FUNC(isa8_cga_m24_device::crtc_update_row));
1735 m_crtc->out_hsync_callback().set(FUNC(isa8_cga_m24_device::hsync_changed));
1736 m_crtc->out_vsync_callback().set(FUNC(isa8_cga_m24_device::vsync_changed));
1737 m_crtc->set_reconfigure_callback(FUNC(isa8_cga_m24_device::reconfigure));
1738 }
1739
isa8_cga_m24_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1740 isa8_cga_m24_device::isa8_cga_m24_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1741 isa8_cga_m24_device(mconfig, ISA8_CGA_M24, tag, owner, clock)
1742 {
1743 }
1744
isa8_cga_m24_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)1745 isa8_cga_m24_device::isa8_cga_m24_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
1746 isa8_cga_device(mconfig, type, tag, owner, clock), m_mode2(0), m_index(0)
1747 {
1748 m_vram_size = 0x8000;
1749 }
1750
1751 ROM_START(cga_m24)
1752 ROM_REGION(0x2000, "gfx1", 0)
1753 ROM_LOAD("m24 graphics board go380 258 pqbq.bin", 0x00000, 0x1000, CRC(04495786) SHA1(ea34ee527c5632d049ec11a7ae0fde9e6dee545f))
1754
1755 ROM_REGION(0x1000, "crtc_prom", 0)
1756 ROM_LOAD("m24 graphics board go380 gi 9433-0088.bin", 0x00000, 0x1000, CRC(5725e660) SHA1(634c2d165d401883a955e144a0abfa2078a47013))
1757 ROM_END
1758
device_rom_region() const1759 const tiny_rom_entry *isa8_cga_m24_device::device_rom_region() const
1760 {
1761 return ROM_NAME(cga_m24);
1762 }
1763
device_reset()1764 void isa8_cga_m24_device::device_reset()
1765 {
1766 isa8_cga_device::device_reset();
1767 m_mode2 = 0;
1768 m_start_offset = 0;
1769 m_chr_gen_offset[0] = m_chr_gen_offset[2] = 0x0000;
1770 m_chr_gen_offset[1] = m_chr_gen_offset[3] = 0x0000;
1771 }
1772
MC6845_RECONFIGURE(isa8_cga_m24_device::reconfigure)1773 MC6845_RECONFIGURE( isa8_cga_m24_device::reconfigure )
1774 {
1775 // just reconfigure the screen, the apb sets it to 256 lines rather than 400
1776 m_screen->configure(width, height, visarea, frame_period);
1777 }
1778
io_write(offs_t offset,uint8_t data)1779 void isa8_cga_m24_device::io_write(offs_t offset, uint8_t data)
1780 {
1781 switch(offset)
1782 {
1783 case 0: case 2: case 4: case 6:
1784 m_index = data;
1785 m_crtc->address_w(data);
1786 break;
1787 case 1: case 3: case 5: case 7:
1788 switch(m_index & 0x1f) // TODO: this is handled by a pal and prom
1789 {
1790 case 0:
1791 data &= 0x7f;
1792 break;
1793 case 9:
1794 if((data < 0x80) && (data != 3))
1795 data = (data << 1) + 1;
1796 break;
1797 case 10:
1798 data = ((data << 1) & 0x1f) | (data & 0x60);
1799 break;
1800 case 11:
1801 data <<= 1;
1802 break;
1803 }
1804 m_crtc->register_w(data);
1805 break;
1806 case 0x0e:
1807 m_mode2 = data;
1808 if((data & 8) && !(data & 1))
1809 m_start_offset = 0x4000;
1810 else
1811 m_start_offset = 0;
1812 break;
1813 default:
1814 isa8_cga_device::io_write(offset, data);
1815 break;
1816 }
1817 }
1818
io_read(offs_t offset)1819 uint8_t isa8_cga_m24_device::io_read(offs_t offset)
1820 {
1821 uint8_t data = 0xff;
1822
1823 switch(offset)
1824 {
1825 case 0x0a:
1826 data = 0xc0 | m_vsync | ( ( data & 0x40 ) >> 4 ) | m_hsync; // 0xc0 == no expansion
1827 break;
1828 case 0x0e:
1829 data = m_mode2;
1830 break;
1831 default:
1832 data = isa8_cga_device::io_read(offset);
1833 break;
1834 }
1835 return data;
1836 }
1837
1838
MC6845_UPDATE_ROW(isa8_cga_m24_device::crtc_update_row)1839 MC6845_UPDATE_ROW(isa8_cga_m24_device::crtc_update_row)
1840 {
1841 if (m_mode2 & 1)
1842 {
1843 m24_gfx_1bpp_m24_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
1844 return;
1845 }
1846
1847 if (m_update_row_type == -1)
1848 return;
1849
1850 y = m_y;
1851 if (m_y >= bitmap.height())
1852 return;
1853
1854 switch (m_update_row_type)
1855 {
1856 case CGA_TEXT_INTEN:
1857 cga_text<false, false, false, false, 16>(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
1858 break;
1859 case CGA_TEXT_INTEN_ALT:
1860 cga_text<false, false, false, true, 16>(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
1861 break;
1862 case CGA_TEXT_INTEN_CG: // this hardware doesn't support composite
1863 break;
1864 case CGA_TEXT_BLINK:
1865 cga_text<true, false, false, false, 16>(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
1866 break;
1867 case CGA_TEXT_BLINK_ALT:
1868 cga_text<true, false, false, true, 16>(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
1869 break;
1870 case CGA_TEXT_BLINK_SI:
1871 break;
1872 case CGA_GFX_1BPP:
1873 cga_gfx_1bpp_update_row(bitmap, cliprect, ma, ra >> 1, y, x_count, cursor_x, de, hbp, vbp);
1874 break;
1875 case CGA_GFX_2BPP:
1876 cga_gfx_2bpp_update_row(bitmap, cliprect, ma, ra >> 1, y, x_count, cursor_x, de, hbp, vbp);
1877 break;
1878 case CGA_GFX_4BPPL:
1879 cga_gfx_4bppl_update_row(bitmap, cliprect, ma, ra >> 1, y, x_count, cursor_x, de, hbp, vbp);
1880 break;
1881 case CGA_GFX_4BPPH:
1882 cga_gfx_4bpph_update_row(bitmap, cliprect, ma, ra >> 1, y, x_count, cursor_x, de, hbp, vbp);
1883 break;
1884 }
1885 }
1886
MC6845_UPDATE_ROW(isa8_cga_m24_device::m24_gfx_1bpp_m24_update_row)1887 MC6845_UPDATE_ROW( isa8_cga_m24_device::m24_gfx_1bpp_m24_update_row )
1888 {
1889 uint8_t const *const videoram = &m_vram[m_start_offset];
1890 uint32_t *p = &bitmap.pix(y);
1891 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
1892 uint8_t const fg = m_color_select & 0x0f;
1893
1894 if (y == 0) CGA_LOG(1,"m24_gfx_1bpp_m24_update_row",("\n"));
1895 for (int i = 0; i < x_count; i++)
1896 {
1897 uint16_t const offset = (((ma + i) << 1 ) & 0x1fff) | ((ra & 3) << 13);
1898 uint8_t data;
1899
1900 data = videoram[offset];
1901
1902 *p++ = palette[(data & 0x80) ? fg : 0];
1903 *p++ = palette[(data & 0x40) ? fg : 0];
1904 *p++ = palette[(data & 0x20) ? fg : 0];
1905 *p++ = palette[(data & 0x10) ? fg : 0];
1906 *p++ = palette[(data & 0x08) ? fg : 0];
1907 *p++ = palette[(data & 0x04) ? fg : 0];
1908 *p++ = palette[(data & 0x02) ? fg : 0];
1909 *p++ = palette[(data & 0x01) ? fg : 0];
1910
1911 data = videoram[offset + 1];
1912
1913 *p++ = palette[(data & 0x80) ? fg : 0];
1914 *p++ = palette[(data & 0x40) ? fg : 0];
1915 *p++ = palette[(data & 0x20) ? fg : 0];
1916 *p++ = palette[(data & 0x10) ? fg : 0];
1917 *p++ = palette[(data & 0x08) ? fg : 0];
1918 *p++ = palette[(data & 0x04) ? fg : 0];
1919 *p++ = palette[(data & 0x02) ? fg : 0];
1920 *p++ = palette[(data & 0x01) ? fg : 0];
1921 }
1922 }
1923
1924 DEFINE_DEVICE_TYPE(ISA8_CGA_CPORTIII, isa8_cga_cportiii_device, "cga_cportiii", "Compaq Portable III CGA")
1925
device_add_mconfig(machine_config & config)1926 void isa8_cga_cportiii_device::device_add_mconfig(machine_config &config)
1927 {
1928 isa8_cga_m24_device::device_add_mconfig(config);
1929
1930 subdevice<screen_device>(CGA_SCREEN_NAME)->set_color(rgb_t(255, 125, 0));
1931 }
1932
isa8_cga_cportiii_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1933 isa8_cga_cportiii_device::isa8_cga_cportiii_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1934 isa8_cga_m24_device(mconfig, ISA8_CGA_CPORTIII, tag, owner, clock)
1935 {
1936 }
1937
1938 ROM_START(cga_cportiii)
1939 ROM_REGION(0x2000, "gfx1", 0)
1940 ROM_FILL(0, 0x2000, 0)
1941 ROM_END
1942
device_rom_region() const1943 const tiny_rom_entry *isa8_cga_cportiii_device::device_rom_region() const
1944 {
1945 return ROM_NAME(cga_cportiii);
1946 }
1947
device_reset()1948 void isa8_cga_cportiii_device::device_reset()
1949 {
1950 isa8_cga_m24_device::device_reset();
1951 m_isa->install_device(0x13c6, 0x13c7, read8smo_delegate(*this, FUNC(isa8_cga_cportiii_device::port_13c6_r)), write8smo_delegate(*this, FUNC(isa8_cga_cportiii_device::port_13c6_w)));
1952 m_isa->install_device(0x23c6, 0x23c7, read8smo_delegate(*this, FUNC(isa8_cga_cportiii_device::port_23c6_r)), write8smo_delegate(*this, FUNC(isa8_cga_cportiii_device::port_23c6_w)));
1953 m_palette->set_pen_color(0, 100, 25, 0);
1954 m_chr_gen_offset[0] = m_chr_gen_offset[2] = 0x0000;
1955 m_chr_gen_offset[1] = m_chr_gen_offset[3] = 0x1000;
1956 }
1957
char_ram_write(offs_t offset,uint8_t data)1958 void isa8_cga_cportiii_device::char_ram_write(offs_t offset, uint8_t data)
1959 {
1960 m_chr_gen_base[offset] = data;
1961 }
1962
char_ram_read(offs_t offset)1963 uint8_t isa8_cga_cportiii_device::char_ram_read(offs_t offset)
1964 {
1965 return m_chr_gen_base[offset];
1966 }
1967
port_13c6_r()1968 uint8_t isa8_cga_cportiii_device::port_13c6_r()
1969 {
1970 return 0x04;
1971 }
1972
port_13c6_w(uint8_t data)1973 void isa8_cga_cportiii_device::port_13c6_w(uint8_t data)
1974 {
1975 }
1976
port_23c6_r()1977 uint8_t isa8_cga_cportiii_device::port_23c6_r()
1978 {
1979 return 0;
1980 }
1981
port_23c6_w(uint8_t data)1982 void isa8_cga_cportiii_device::port_23c6_w(uint8_t data)
1983 {
1984 m_mode2 = data & 1;
1985 if(BIT(data, 3))
1986 m_isa->install_memory(0xb8000, 0xb9fff, read8sm_delegate(*this, FUNC(isa8_cga_cportiii_device::char_ram_read)), write8sm_delegate(*this, FUNC(isa8_cga_cportiii_device::char_ram_write)));
1987 else
1988 m_isa->install_bank(0xb8000, 0xb8000 + 0x8000 - 1, "bank_cga", &m_vram[0]);
1989 }
1990
1991