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