1
0
Fork 0

Add support for monochrome mode:

- EGA and VGA mode 0x0F (implement plane masking in the attribute controller)
- re-factor EGA monitor emulation (attribute controller bit is used to detect monochrome mode, horizontal frequency to choose 16/64 colors)

Hardware blinking in graphics mode is still not supported.

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3813
This commit is contained in:
Ralf Grillenberger 2013-01-26 22:01:32 +00:00
parent 2fea508f7f
commit 81226995de
5 changed files with 108 additions and 37 deletions

View file

@ -427,6 +427,10 @@ void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal);
void VGA_DAC_SetEntry(Bitu entry,Bit8u red,Bit8u green,Bit8u blue);
void VGA_ATTR_SetPalette(Bit8u index,Bit8u val);
typedef enum {CGA, EGA, MONO} EGAMonitorMode;
void VGA_ATTR_SetEGAMonitorPalette(EGAMonitorMode m);
/* The VGA Subfunction startups */
void VGA_SetupAttr(void);
void VGA_SetupMemory(Section* sec);

View file

@ -23,22 +23,70 @@
#define attr(blah) vga.attr.blah
void VGA_ATTR_SetPalette(Bit8u index,Bit8u val) {
vga.attr.palette[index] = val;
if (vga.attr.mode_control & 0x80) val = (val&0xf) | (vga.attr.color_select << 4);
val &= 63;
val |= (vga.attr.color_select & 0xc) << 4;
if (GCC_UNLIKELY(machine==MCH_EGA)) {
if ((vga.crtc.vertical_total | ((vga.crtc.overflow & 1) << 8)) == 260) {
// check for intensity bit
if (val&0x10) val|=0x38;
else {
val&=0x7;
// check for special brown
if (val==6) val=0x14;
void VGA_ATTR_SetEGAMonitorPalette(EGAMonitorMode m) {
// palette bit assignment:
// bit | pin | EGA | CGA | monochrome
// ----+-----+------------+-----------+------------
// 0 | 5 | blue | blue | nc
// 1 | 4 | green | green* | nc
// 2 | 3 | red | red* | nc
// 3 | 7 | blue sec. | nc | video
// 4 | 6 | green sec. | intensity | intensity
// 5 | 2 | red sec. | nc | nc
// 6-7 | not used
// * additive color brown instead of yellow
switch(m) {
case CGA:
//LOG_MSG("Monitor CGA");
for (Bitu i=0;i<64;i++) {
vga.dac.rgb[i].red=((i & 0x4)? 0x2a:0) + ((i & 0x10)? 0x15:0);
vga.dac.rgb[i].blue=((i & 0x1)? 0x2a:0) + ((i & 0x10)? 0x15:0);
// replace yellow with brown
if ((i & 0x17) == 0x6) vga.dac.rgb[i].green = 0x15;
else vga.dac.rgb[i].green =
((i & 0x2)? 0x2a:0) + ((i & 0x10)? 0x15:0);
}
}
break;
case EGA:
//LOG_MSG("Monitor EGA");
for (Bitu i=0;i<64;i++) {
vga.dac.rgb[i].red=((i & 0x4)? 0x2a:0) + ((i & 0x20)? 0x15:0);
vga.dac.rgb[i].green=((i & 0x2)? 0x2a:0) + ((i & 0x10)? 0x15:0);
vga.dac.rgb[i].blue=((i & 0x1)? 0x2a:0) + ((i & 0x8)? 0x15:0);
}
break;
case MONO:
//LOG_MSG("Monitor MONO");
for (Bitu i=0;i<64;i++) {
Bit8u value = ((i & 0x8)? 0x2a:0) + ((i & 0x10)? 0x15:0);
vga.dac.rgb[i].red = vga.dac.rgb[i].green =
vga.dac.rgb[i].blue = value;
}
break;
}
// update the mappings
for (Bit8u i=0;i<0x10;i++)
VGA_ATTR_SetPalette(i,vga.attr.palette[i]);
}
void VGA_ATTR_SetPalette(Bit8u index, Bit8u val) {
// the attribute table stores only 6 bits
val &= 63;
vga.attr.palette[index] = val;
// apply the plane mask
val = vga.attr.palette[index & vga.attr.color_plane_enable];
// replace bits 4-5 if configured
if (vga.attr.mode_control & 0x80)
val = (val&0xf) | (vga.attr.color_select << 4);
// set bits 6 and 7 (not relevant for EGA)
val |= (vga.attr.color_select & 0xc) << 4;
// apply
VGA_DAC_CombineColor(index,val);
}
@ -126,7 +174,14 @@ void write_p3c0(Bitu /*port*/,Bitu val,Bitu iolen) {
break;
case 0x12: /* Color Plane Enable Register */
/* Why disable colour planes? */
attr(color_plane_enable)=(Bit8u)val;
/* To support weird modes. */
if ((attr(color_plane_enable)^val) & 0xf) {
// in case the plane enable bits change...
attr(color_plane_enable)=(Bit8u)val;
for (Bit8u i=0;i<0x10;i++)
VGA_ATTR_SetPalette(i,vga.attr.palette[i]);
} else
attr(color_plane_enable)=(Bit8u)val;
/*
0 Bit plane 0 is enabled if set.
1 Bit plane 1 is enabled if set.
@ -180,9 +235,8 @@ void write_p3c0(Bitu /*port*/,Bitu val,Bitu iolen) {
}
if (attr(color_select) ^ val) {
attr(color_select)=(Bit8u)val;
for (Bit8u i=0;i<0x10;i++) {
for (Bit8u i=0;i<0x10;i++)
VGA_ATTR_SetPalette(i,vga.attr.palette[i]);
}
}
/*
0-1 If 3C0h index 10h bit 7 is set these 2 bits are used as bits 4-5 of

View file

@ -213,19 +213,5 @@ void VGA_SetupDAC(void) {
IO_RegisterReadHandler(0x3c8,read_p3c8,IO_MB);
IO_RegisterWriteHandler(0x3c9,write_p3c9,IO_MB);
IO_RegisterReadHandler(0x3c9,read_p3c9,IO_MB);
} else if (machine==MCH_EGA) {
for (Bitu i=0;i<64;i++) {
if ((i&4)>0) vga.dac.rgb[i].red=0x2a;
else vga.dac.rgb[i].red=0;
if ((i&32)>0) vga.dac.rgb[i].red+=0x15;
if ((i&2)>0) vga.dac.rgb[i].green=0x2a;
else vga.dac.rgb[i].green=0;
if ((i&16)>0) vga.dac.rgb[i].green+=0x15;
if ((i&1)>0) vga.dac.rgb[i].blue=0x2a;
else vga.dac.rgb[i].blue=0;
if ((i&8)>0) vga.dac.rgb[i].blue+=0x15;
}
}
}

View file

@ -1233,6 +1233,29 @@ void VGA_SetupDrawing(Bitu /*val*/) {
// Display end
vga.draw.delay.vdend = vdend * vga.draw.delay.htotal;
// EGA frequency dependent monitor palette
if (machine == MCH_EGA) {
if (vga.misc_output & 1) {
// EGA card is in color mode
if ((1.0f/vga.draw.delay.htotal) > 19.0f) {
// 64 color EGA mode
VGA_ATTR_SetEGAMonitorPalette(EGA);
} else {
// 16 color CGA mode compatibility
VGA_ATTR_SetEGAMonitorPalette(CGA);
}
} else {
// EGA card in monochrome mode
// It is not meant to be autodetected that way, you either
// have a monochrome or color monitor connected and
// the EGA switches configured appropriately.
// But this would only be a problem if a program sets
// the adapter to monochrome mode and still expects color output.
// Such a program should be shot to the moon...
VGA_ATTR_SetEGAMonitorPalette(MONO);
}
}
vga.draw.parts_total=VGA_PARTS;
/*
6 Horizontal Sync Polarity. Negative if set

View file

@ -1046,6 +1046,8 @@ bool INT10_SetVideoMode(Bit16u mode) {
break;
case M_LIN4:
case M_EGA:
if (CurMode->mode == 0x0f)
gfx_data[0x7]=0x05; // only planes 0 and 2 are used
gfx_data[0x6]|=0x05; //graphics mode at 0xa000-affff
break;
case M_CGA4:
@ -1075,12 +1077,14 @@ bool INT10_SetVideoMode(Bit16u mode) {
att_data[0x10]=0x01; //Color Graphics
switch (CurMode->mode) {
case 0x0f:
att_data[0x10]|=0x0a; //Monochrome
att_data[0x01]=0x08;
att_data[0x04]=0x18;
att_data[0x05]=0x18;
att_data[0x09]=0x08;
att_data[0x0d]=0x18;
att_data[0x12]=0x05; // planes 0 and 2 enabled
att_data[0x10]|=0x0a; // monochrome and blinking
att_data[0x01]=0x08; // low-intensity
att_data[0x04]=0x18; // blink-on case
att_data[0x05]=0x18; // high-intensity
att_data[0x09]=0x08; // low-intensity in blink-off case
att_data[0x0d]=0x18; // high-intensity in blink-off
break;
case 0x11:
for (i=1;i<16;i++) att_data[i]=0x3f;