VOGONS


CGA pseudo-graphic modes

Topic actions

Reply 120 of 153, by SoftCat

User metadata
Rank Member
Rank
Member
GloriousCow wrote on 2025-12-26, 00:26:

Just be careful playing around with a Hercules's timings, if you use something like a 5151 the horizontal sync is directly driven and there are tales of people making them go pop in seconds.

Thanks for the warning.
This mode is for consumer PAL/SCECAM TVs with a horizontal frequency of 15625 Hz.

Reply 121 of 153, by superfury

User metadata
Rank l33t++
Rank
l33t++

Interestingly EGA mode F should be able to support 4 grayscale colors (including black) on a MDA monitor. Assuming you reprogram it's registers at least (I have a program that tests that in UniPCemu's pascal code files).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 122 of 153, by mkarcher

User metadata
Rank l33t
Rank
l33t
superfury wrote on 2025-12-26, 11:12:

Interestingly EGA mode F should be able to support 4 grayscale colors (including black) on a MDA monitor. Assuming you reprogram it's registers at least (I have a program that tests that in UniPCemu's pascal code files).

Indeed. Given you reprogram the palette suitably and disable blinking, you should be able to get all 4 possible combinations of VIDEO and INTENSITY on the 9-pin monitor connector. Whether the unusual combination VIDEO=0, INTENSITY=1, which is not generated by the MDA or Hercules card, actually results in a fourth shade of "gray" depends on the monitor. There might be monitors that generally only support 3 intensities, always displaying black if VIDEO=0, ignoring INTENSITY.

Reply 123 of 153, by superfury

User metadata
Rank l33t++
Rank
l33t++
mkarcher wrote on 2025-12-26, 11:37:
superfury wrote on 2025-12-26, 11:12:

Interestingly EGA mode F should be able to support 4 grayscale colors (including black) on a MDA monitor. Assuming you reprogram it's registers at least (I have a program that tests that in UniPCemu's pascal code files).

Indeed. Given you reprogram the palette suitably and disable blinking, you should be able to get all 4 possible combinations of VIDEO and INTENSITY on the 9-pin monitor connector. Whether the unusual combination VIDEO=0, INTENSITY=1, which is not generated by the MDA or Hercules card, actually results in a fourth shade of "gray" depends on the monitor. There might be monitors that generally only support 3 intensities, always displaying black if VIDEO=0, ignoring INTENSITY.

That fourth brightness is documented on the wiki page, though: https://en.wikipedia.org/wiki/IBM_Monochrome_Display_Adapter
Under Capabilities.
The mentioned footnote page does mention that that 'dark green' might be barely visible on some monitors or indistinguishable from black.

That does make me question: what happens on a genuine IBM MDA monitor?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 124 of 153, by SoftCat

User metadata
Rank Member
Rank
Member
superfury wrote on 2025-12-26, 11:12:

Interestingly EGA mode F should be able to support 4 grayscale colors (including black) on a MDA monitor. Assuming you reprogram it's registers at least (I have a program that tests that in UniPCemu's pascal code files).

On an EGA with 64 KB of video RAM, F mode will only display one page. Overall, this mode is a poor choice. It would be better if they made it 720x350. To achieve this, you'd need to set the pixel clock on the EGA to 16.257 MHz and on the VGA to 28.322 MHz. You'll also need to adjust the CRTC settings slightly.

Reply 125 of 153, by mkarcher

User metadata
Rank l33t
Rank
l33t
superfury wrote on 2025-12-26, 15:05:

That fourth brightness is documented on the wiki page, though: https://en.wikipedia.org/wiki/IBM_Monochrome_Display_Adapter
Under Capabilities.

In my oppinion, the claim that the levels are (exactly) 33%, 66% and 100% should not be on Wikipedia due to WP:NOR. Typical monochrome monitors have user-adjustable brightness and contrast controls, and if I remember correctly, "brightness" directly sets the brightness level of "VIDEO=1/INTENSITY=1" (it defines "100%"), and the contrast control allows an arbitrary setting of "normal video" between 0% and 100%. So adjusting it to 66% is possible, but clearly not given in any way.

superfury wrote on 2025-12-26, 15:05:

That does make me question: what happens on a genuine IBM MDA monitor?

Page D-24 of the first edition of the IBM PC Technical Reference Manual has the schematics of the 5151 (the "genuine IBM MDA monitor"). Video input is handled by the 7406 open-collector hex inverter IC 201. R214/D203 are a shunt regulator that provide 5V Vcc to that chip, R204 and R202, while (A) is connected to the stabilized 15V supply. The 7406 is capable of handling up to 15V at its open-collector outputs, so you don't need to worry whether the 15V fries the chip.

Furthermore, the output of the video input circuit is the right end of R207, which enters the cathode drive amplifier at the point labeled "V1", with ground being connected to "E1". The first active element in the cathode drive amplifier is TR19, a bipolar transistor. This transistor will be "completely off" as long as the base voltage is below 0.6V, and during normal operation, the base voltage will be around 0.7V. I'm unable to explain what exactly happens in that circuit in its active region, but basically, higher voltage at V1 means higher current through R208, which means more current through TR19, which will pull more current through TR20, and thus considerably more current through R209, which counteracts the voltage at V1. This counteraction is used to generate a stable amplification via TR19, independent of component variations and the temperature of TR19. The input circuit of the cathode drive amplifier seems to be cascode circuit. If you happen to be interested in the analog design, this keyword enables you to dig deeper. The main point is that anything below 0.6V at E1 is treated the same way, as "completely off". The other end of the operating region is set by the 6.8V at the base of TR20 and/or the voltage drop across R211, but it is likely higher than +5V at the input, so it will not be relevant for the further discussion.

Now let's look at how the VIDEO signal is processed. The VIDEO signal first enters a discrete inverting amplifier built from R201 and TR18. The capacitor in parallel to the base resistor enhances response to high frequencies and thus will increase image sharpness. I assume this provides better high-frequency response to the VIDEO signal than to the INTESITY signal, which is a sign that you likely get sub-par results assuming you want to use the INTENSITY signal per-pixel (which neither the MDA nor the Hercules card does). The externally inverted VIDEO signal is then sent through the inverter 9->8 of IC201, which will pull its output to ground if VIDEO is low. The SN7406 is quite good at pulling its output low (I didn't bother to check the data sheet right now, but I know its superior drive capability is the reason the AT uses the 7406 over the 7405 in its keyboard interface), so the cathode of D202 will be close to ground (0.3V to 0.5V), which is below the operating region of the cathode drive amplifier. So if VIDEO is low, the image is black, no matter what level the INTENSITY signal provides.

Only if VIDEO is high, the intensity signal gets relevant. It is connected to the input named "DUAL", which is inverted twice using the 7406 chip. The first time using the inverter 1->2 with a 5V pull-up R204, and a second time using the inverter 3->4. That inverter pulls pin 4 to ground if INTENSITY is low, and leaved pin 4 "open circuit" if INTENSiTY is high. If pin 4 is open circuit (high intensity), the circuit from +5V via R205, D201, the contrast pot and R206 to +15V does not conduct any current, because the diode D201 is obviously reverse biased. The circuit thus behaves "as if" D201, the contrast pot and R206 are removed from the circuit. This means all current through R205 continues to flow into the cathode drive amplifier (if VIDEO is high). On the other hand, if intensity is low, there is current flow via R206 (1K) and the contrast pot (500 ohms) into pin 4 of the inverter. Assuming no wiper current (which is not exactly true, but will do for simplicity right now), the wiper voltage of the contrast pot ranges between 0V and 5V if "low intensity" is requested. With a wiper voltage above 4.3V, D201 is still revese biased, so there is no response to the intensity signal if the wiper is close to the +5V end, i.e. there will be no contrast. On the other end of the contrast range, the wiper is directly connected to pin 4 of the inverter and pulled that hard to ground that the voltage at the cathode of D201, which is mirrored at the cathode of D202, is insufficient to turn on the cathode amplifier, making the "low intensity" signal completely black.

So, in summary, the circuit confirms my experience with monochrome monitors: You set the overall brightness (directly used for high-intensity video) using the brightness pot (which is in the CRT circuit), and you can then adjust the "normal intensity" brightness using the contrast pot, with an adjustment range including "normal video is invisible" to "normal video is as bright as high intensity" (both extremes are typically useless). The circuit of the 5151 does not allow a fourth shade of green in "intensity only" mode, because pin 8 of the inverter will pull all current that could enter the cathode amplifier if VIDEO is low, so VIDEO low directly implies "black" (unless you yank up the brightness to an insane level that makes even black light up the tube).

Reply 126 of 153, by mkarcher

User metadata
Rank l33t
Rank
l33t
SoftCat wrote on 2025-12-26, 17:25:

On an EGA with 64 KB of video RAM, F mode will only display one page. Overall, this mode is a poor choice. It would be better if they made it 720x350. To achieve this, you'd need to set the pixel clock on the EGA to 16.257 MHz and on the VGA to 28.322 MHz. You'll also need to adjust the CRTC settings slightly.

On the other hand, having a monochrome mode of 720x350 and a color mode of 640x350 means that software developers that want to support both modes need to deal with different pixel aspect ratios, and might need to create bitmap artifacts for the user interface twice, while single-color display artifacts can be reused between color and monochrome mode if you have the same resolution. Furthermore, many graphics libraries of that time hardcoded the horizontal width in the pixel offset generation, which again would mean separate code for color and monochrome video support. So there is a trade-off between uniformness of mono/color and the resolution available in the monochrome case. IBM chose uniformness over maximum resolution, possibly in an attempt to be incompatible with the Hercules resolution and push software developers to develop EGA mono/color software instead of supporting the Hercules card with its oddball horizontal resolution.

Reply 127 of 153, by GloriousCow

User metadata
Rank Oldbie
Rank
Oldbie
mkarcher wrote on 2025-12-26, 18:13:

So, in summary, the circuit confirms my experience with monochrome monitors: You set the overall brightness (directly used for high-intensity video) using the brightness pot (which is in the CRT circuit), and you can then adjust the "normal intensity" brightness using the contrast pot, with an adjustment range including "normal video is invisible" to "normal video is as bright as high intensity" (both extremes are typically useless). The circuit of the 5151 does not allow a fourth shade of green in "intensity only" mode, because pin 8 of the inverter will pull all current that could enter the cathode amplifier if VIDEO is low, so VIDEO low directly implies "black" (unless you yank up the brightness to an insane level that makes even black light up the tube).

Excellent analysis - what I wouldn't give for a comprehensive, well-photographed gallery of various test patterns in each mode on multiple monitor models. I know there's a whole galaxy of monitor models, but coverage of IBM's product line should be feasible.

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 128 of 153, by SoftCat

User metadata
Rank Member
Rank
Member
mkarcher wrote on 2025-12-26, 18:20:

On the other hand, having a monochrome mode of 720x350 and a color mode of 640x350 means that software developers that want to support both modes need to deal with different pixel aspect ratios, and might need to create bitmap artifacts for the user interface twice, while single-color display artifacts can be reused between color and monochrome mode if you have the same resolution. Furthermore, many graphics libraries of that time hardcoded the horizontal width in the pixel offset generation, which again would mean separate code for color and monochrome video support. So there is a trade-off between uniformness of mono/color and the resolution available in the monochrome case. IBM chose uniformness over maximum resolution, possibly in an attempt to be incompatible with the Hercules resolution and push software developers to develop EGA mono/color software instead of supporting the Hercules card with its oddball horizontal resolution.

If the BIOS had supported two monochrome graphics modes (640x350 and 720x350), the EGA graphics card wouldn't have become more expensive. So, this is pure marketing.

Reply 129 of 153, by SoftCat

User metadata
Rank Member
Rank
Member

According to my calculations, it should be 80 colors on a CGA monitor with IRGB. Can anyone test this on a real CGA?

Reply 130 of 153, by Benedikt

User metadata
Rank Oldbie
Rank
Oldbie
SoftCat wrote on 2026-01-24, 23:43:

According to my calculations, it should be 80 colors on a CGA monitor with IRGB.

Can you elaborate? How do “80 colors on a CGA monitor with IRGB” work?

Reply 131 of 153, by SoftCat

User metadata
Rank Member
Rank
Member
Benedikt wrote on 2026-01-25, 22:03:

Can you elaborate? How do “80 colors on a CGA monitor with IRGB” work?

Each character cell contains a symbol with code 177, the symbol color is c1, and the background color is c2. On the second video page, it's the other way around: the symbol color is c2 and the background color is c1. The pages switch every frame.

Reply 132 of 153, by jal

User metadata
Rank Oldbie
Rank
Oldbie

30Hz color 😁

Reply 133 of 153, by superfury

User metadata
Rank l33t++
Rank
l33t++

I'm wondering a bit.
If CGA needs to fetch character/attribute 1 MA cycle early, then what about the font ROM? Would it need to fetch that early too? So effectively it needs one extra character clock for those? Or is it only one cycle, so 2 cycles before the character clock? Does the same count for horizontal total for it being early by 2 cycles(1 for character, 1 for attribute, assuming like on EGA, character fetch also fetches the character ROM)? Double that probably on dividing horizontal timings by 2 (dot clock divide by 2, like in 40x25 modes)?
That would also mean that the scanline counter used for the next row is increased or cleared(for the next row being vertical total) at that point as well? And perhaps that scanline counter is immediately reverted to it's previous value before the next clock (to make horizontal total and vertical total perform correctly)?

Edit: So that's 8 pixel clocks (4 for character, 4 for attribute) before horizontal total in text mode? And 4 pixel clocks (4 for attribute) in all graphics modes? So it's basically operating in half-character clock units (plain character clock units if it's having halved dot clock, like in 40 column mode)?
Also, 4 clocks is interesting. Like exactly a quarter the 8088 memory byte access timing (8088 running at a quarter of the CGA speed)?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 134 of 153, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie

Well, to start actually outputting the pixel data for a text character, the character, attribute, and bit pattern from the character ROM all need to have been fetched. But these are pipelined and done in parallel as much as possible. For +HRES text mode, character is latched at hdot 7 (relative to an arbitrary point in the CGA's internal timing cycle) and the corresponding attribute is latched at hdot 17. Also on hdot 17 the shift register is loaded with the bit pattern from the character ROM, so that's going on at the same time that the attribute is being fetched from the VRAM.

Reply 135 of 153, by superfury

User metadata
Rank l33t++
Rank
l33t++
reenigne wrote on 2026-01-28, 11:29:

Well, to start actually outputting the pixel data for a text character, the character, attribute, and bit pattern from the character ROM all need to have been fetched. But these are pipelined and done in parallel as much as possible. For +HRES text mode, character is latched at hdot 7 (relative to an arbitrary point in the CGA's internal timing cycle) and the corresponding attribute is latched at hdot 17. Also on hdot 17 the shift register is loaded with the bit pattern from the character ROM, so that's going on at the same time that the attribute is being fetched from the VRAM.

Really? 10 cycles to read a single character from VRAM? Isn't that way more than what the rendering part uses (it needs a new character/data combination every 8 dot clocks (in EGA/VGA terminology to compare, dot clocks are essentially based on the CGA mode control register halving horizontal timings or not (80 column vs 40 column mode)), so no more than 4 dot clocks (half a character) for loading either character or data, otherwise it's starving it's buffers (it renders 1 pixel(doubled or not) each dot clock)?

Yeah, I'd think that the character ROM is properly pipelined by inputting the character byte as it's read from VRAM, directly piped into the address of the ROM's base address (combined with the character's inner row counter for addressing, just like VGA's character times 32 plus inner row mechanism, but using a simple address bus instead. Probably roughly following the same timing as the attribute byte)?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 136 of 153, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie

You're right, I screwed that up - I was counting half-hdots, not hdots. Characters are latched at half-hdot 7 and 23 (so 8 hdots apart) and attributes are latched at half-hdot 17 and 1 (also 8 hdots apart) but they're not evenly spaced in the cycle - the time from attribute latched to character latched is 3 hdots and the time from character latched to attribute latched is 5 hdots.

Reply 137 of 153, by superfury

User metadata
Rank l33t++
Rank
l33t++
reenigne wrote on 2026-01-28, 15:51:

You're right, I screwed that up - I was counting half-hdots, not hdots. Characters are latched at half-hdot 7 and 23 (so 8 hdots apart) and attributes are latched at half-hdot 17 and 1 (also 8 hdots apart) but they're not evenly spaced in the cycle - the time from attribute latched to character latched is 3 hdots and the time from character latched to attribute latched is 5 hdots.

That's interesting. So why isn't it latching character or attribute every 4 hdots for both?

With a bit of modification of my current emulation, I've managed to get the 4-clock timing to operate properly now.
So right now, it's fetching the character byte 8 dot clocks before the next scanline and the attribute byte 4 clocks before the next scanline. The same counts are also applied to active display character/attribute bytes.

It was quite some work to get the new timing mechanism of fetching on the previous scanline's end to operate properly.
Mainly due to all counters being reset for handling horizontal timing in various ways.
Right now, the (S)VGA is performing reads directly on the clocks themselves, while CGA/MDA handle split character and attribute fetches from VRAM (every 4 cycles right now).

So does the 4 color graphics mode.
From what I remember, just the monochrome mode still is handled with old timings (fetching VGA-style).

With these latest changes, I'm back to getting the CGA graphics modes to run properly now. And I mean all of them: both monochrome and color modes seem to fail operating properly now (and 40 column text mode only seems to get half the display it should (running in RGBI mode for clarity on what's happening)).
Needed to switch the adapter from byte mode in text mode to word mode (like on EGA/VGA) to get it to handle the character clocks properly.
Ofc 8088 MPH etc. won't run at all anymore now due to these issues.
Edit: Managed to fix all CheckIt's reported modes. Just 640x200 monochrome graphics seems to have every other pixel line rendered incorrectly? So horizontal timings work fine, vertical timings (perhaps MAP13?) seem to mess up the pixels rendered every odd scanline.

Last edited by superfury on 2026-01-30, 00:42. Edited 1 time in total.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 138 of 153, by SoftCat

User metadata
Rank Member
Rank
Member

reenigne, you have 666 messages. To practice magic, you need to get a black cat like this.

Reply 139 of 153, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
SoftCat wrote on 2026-01-29, 21:43:

reenigne, you have 666 messages. To practice magic, you need to get a black cat like this.

Won't this one do?