There is an issue with the EGA code that I noticed early on, but I have not mentioned it yet, because I was not sure what was going on exactly. I have found most of the answers now, so let me explain.
The issue was with the EGA palette. EGA has a palette of 64 colours in total, of which you can use up to 16 at a time (in 4-plane mode, as I was using). So I tried to create an optimized palette for a blue gradient, just like I did for the VGA version. I used a total of 11 different colours, from black to white, with a blue hue. However, when I tested this code in dosbox, it did not look as good as I expected. Let’s see the video again that I posted in part 2:
As you can see, there are far less than 11 different shades. There is black, white, and perhaps 3 different shades of blue. But why? Is dosbox bugged? That is what I thought originally, since I got this when I ran it on my GeForce GTX460 (sadly I had no better way to capture it than with the camera of my mobile phone):
Perhaps it’s not that obvious from the video, but all 11 shades were visible. So originally I thought dosbox was bugged. I checked its source code and indeed, its EGA palette deliberately duplicated the same 16 colours 4 times. I must have checked the EGA documentation a dozen times, but I didn’t find an explanation for it.
Then I figured I’d dig out my old 486 machine, and test it on there. It may have an SVGA card, not an actual EGA card, but at least it’s from an era where EGA compatibility might still have mattered somewhat, so it is likely to be more compatible than today’s videocards (which rarely even need to work in VGA mode, let alone EGA or CGA).
I was somewhat shocked when I saw that it did the same remapping that dosbox did. Whatever happened to those 64 colours in the EGA palette? Apparently there is a method to this madness, but what? Eventually I landed upon this blog post, and there was an explanation at last! Apparently IBM wanted to keep compatibility between CGA monitors and EGA cards, and vice versa. So an EGA card could be connected to a CGA monitor, in which case only the 200-line modes could be used (320×200 and 640×200). There is a logistic problem here: CGA monitors only support 4 different signals for colour: red, green, blue and intensity. Therefore they are only capable of 16 different colours.
IBM also made a high-resolution EGA monitor, the 5154. With this monitor, you could also use the 350-line modes. This monitor has 6 signals for colour: red, green and blue each have their own intensity signal, which leads to 2 bits per colour, giving us the magical 64-colour EGA palette. So then it hit me: I had been looking at the wrong manual all along! Now if we look at the manual of the 5154, it is explained very clearly:
The IBM Enhanced Color Display is an advanced color display capable of operating in two separate modes. Mode 1 is a 16 color ~ 640 by 200 overscan mode with a horizontal scan frequency of 15.75 kHz. Mode 2 is a 64 color 640 by 350 mode with a horizontal scan frequency of 21.8 kHz. Both modes are non-interlaced. The monitor determines which mode to operate in by decoding the vertical sync polarity.
When operating in Mode 1, the display maps the 4 input bits into 16 of the possible 64 colors as shown in the following chart.
So there it is: the EGA monitor acts the same as a CGA monitor when in 200-line mode. This way an EGA monitor can be connected to a CGA card as well. Also, the output of an EGA card in 200-line mode is always the same, regardless of whether you use a CGA or EGA monitor. Only the 16 CGA colours can be used.
Well, that’s quite nasty. Only in 640×350 mode the entire palette is available. But that mode requires nearly the entire 128kb of memory (and in fact, there are even 64kb EGA cards, which can only use 640×350 in monochrome and 4-colour mode). This means that you can no longer use any of the trickery we’ve come to know and love, such as double-buffering, hardware-scrolling, and fast filling.
Since this apparently is just hardwired into the monitor, there doesn’t seem to be a way to enable the full palette in 320×200 mode through software. The only hack I can think of is to use the 640×350 mode, but then set up a smaller window. The 350 lines are pretty much fixed, since that signal is what triggers the monitor’s mode. I’m not sure if it is possible to use a negative polarity while outputting a 200-line signal (or at least something closer to 200 than 350), and if so, if the monitor would interpret that as an EGA signal or not. However, it is possible to change the horizontal frequency, so you could at least get a 320×350 mode. Then you could further tweak the CRT controller to cut off after the 200th scanline, so you have a 320×200 viewport in the 320×350 mode. That way you reclaim the memory you’d need for double-buffering and other trickery. The only downside would be that the aspect ratio would be wrong.
But that is assuming we are dealing with real EGA of course. Which I don’t have in the first place. My machines are VGA or better. And then it’s a slightly different story. VGA monitors are completely different from CGA and EGA monitors. They have analog inputs. So in this case, the monitor is not doing anything. It’s the video card that’s emulating a real EGA set up. It emulates the EGA palette by remapping it onto the VGA palette. So the first 64 colours in the 256 colour VGA palette are the total 64 possible colours of EGA. The EGA palette indexes into these colours. When you set an EGA mode, the VGA palette is overwritten with the EGA colours. If you set a 200-line mode, you get the limited CGA palette, whereas if you set a 350-line mode, you get the full EGA palette.
But then the solution is quite simple: Just detect whether you are running on a VGA card, and if so, then overwrite the VGA palette with the proper EGA palette after you set a 200-line mode. So that’s what I did, and now it looks like this (and it not only works correctly on real VGA, but also in dosbox, so I could do a direct recording again):
This is what EGA *could* have looked like, had IBM not decided to remain compatible with CGA monitors in 200-line modes. I just can’t get over how little sense this makes. 320×200 is a much more useful mode than 640×350 for any kind of animated graphics. The lower resolution means it is a lot less heavy on the CPU, and as mentioned before, it is more friendly to the memory, allowing offscreen buffers which can be used for double-buffering, scrolling, fast blt/mask operations via the EGA latches and whatnot. With the full 64-colour palette, EGA could have looked quite decent. But with just the 16 CGA colours, it doesn’t even look as good as other 16-colour systems such as the C64. The CGA colours are quite bright and harsh.
Anyway, a big thanks to Andrew Jenner, whose blog pointed out the weirdness of EGA’s 16 colours in 200-line modes.