HGC cards on IBM PCs used to be able to run CGA software by using a CGA emulator. How exactly did those programs work? What were the limitations?
3 Answers
How exactly did those programs work?
They were based on the ability of the Hercules card use the CGA's memory space.
The original MDPA (*1) had (only) 4 KiB of memory mapped at B0000h, while the CGA had 16 KiB of Memory at B8000h. The Hercules card in contrast had 64 KiB of memory (*2), starting at B0000h. To avoid conflicts with a CGA in the same system the upper 32 KiB were by default disabled. By default the Hercules was 100% compatible. In fact, so compatible that the PCs BIOS did recognize and use it as MDA (with 4 KiB Memory). Unlike the MDA, the Hercules card did offer a full graphics mode of 720x348 (*3,4), which occupied 32 KiB Memory, thus offering up to two pages.
CGA emulations used the fact that the second 32 KiB were not only free (when only the first graphics page was used) but also that memory could be located where the CGA's 16 KiB are, at B8000h..BBFFFh. Programs assuming a CGA (and direct screen access) would go ahead and paint their output into this memory instead. A timer controlled interrupt would now read the virtual CGA buffer at B8000h and transform its content into the real Hercules buffer at B0000h. On fast machines that could happen for every frame.
This was also supported by the fact that while many programs did direct screen updates, configuration was mostly done via BIOS calls, which could also be intercepted by the emulation and handled accordingly. For games with direct control of the CGA's registers, patches were sometimes available.
In fact, some games even skipped programming a Hercules mode by using a built-in (third party) CGA emulation. Accolade's well known Test Drive for example.
What were the limitations?
Most are related to the fact that the conversion of colour and resolution was done in software. To make it happen, the emulator had to steal the cycles to do so from the game. While not an issue with later PCs, it was a deal breaker early on.
Most notable Speed - Games got slowed down. While not much of an issue for round based or adventure games, it was real hurdle for real time/action games.
As well as Lag - One way to reduce the impact on the game performance was to skip frames. Doing the conversion only every second, third or fourth frame, reducing the effective frame rate. Again sometimes to an unplayable low when it came to (re)action games.
Weird Screen Format - Again due to the complexity of conversion, some emulators offered modes where less complex calculations were used by restricting the display area and colour resolution. As a result, only a part of the screen was used (or parts of the picture cropped) and colour information was dropped.
The other big drawbacks were ugly pictures due to the fact that converting a colour picture to monochrome always loses information. Unlike on a TV, there was no grayscale. Depending on the software this was compensated by replacing the colours by fixed patterns. This worked fine on pictures with sharp contrasts (i.e. always black lines in between) but usually only gave a rough impression of different coloured areas. With graphics based on colours (like with 160x200 mode) and fine details the result was awful. Keep in mind, these were just replacement patterns and nothing like real dithering.
And last, programs that manipulated the CGA's (6845) registers directly did not work at all. There weren't many and some emulators even had patches for common ones, still another hurdle to take.
*1 - Monochrome Display and Printer Adapter as the original IBM MDPA also offered a parallel interface. Obviously IBM assumed that an office user would need a printer interface anyway, thus creating the eventual first Multi-Function-Card :))
*2 - The large memory was meant to support loadable character sets and full graphics, as its developer wanted to use Thai characters.
*3 - Descriptions often mention 350 lines, but the last two weren't visible.
*4 - 720x350 at 50 Hz is, BTW, what can be done with a standard CRT when tweaking within the (European) boundaries.
-
Did Test Drive use the second-page trick on the Hercules to avoid having to copy data around? (Admittedly, it could change its base framebuffer address to 0xB000...) Jul 6, 2018 at 13:45
-
3“720x350 at 50 Hz is, BTW, PAL resolution.” — No, it isn't. First, vertical resolution of PAL is 576 lines (interlaced). That's way more than 350. Second, PAL has no pixels; the horizontal resolution is determined by the input signal and the frequency the display can handle. The 720 pixels were standardized much later in the DV format, which as digital format had to decide on a pixel size.– celtschkJul 6, 2018 at 21:43
-
1@celtschk, note that PAL visible resolution of 576 scanlines is at the 25 Hz frame rate. But Hercules has a 50 Hz refresh rate, so it would be more accurate to compare to the PAL field rate of 50 Hz with 288 visible scanlines out of 312. So it is Hercules with the higher vertical resolution, not PAL. I'm not aware of converting Hercules (or CGA) output to PAL/NTSC for display on a TV being a normal thing. I suspect Raffzhan means a PAL TV tube had the specs to be made into a computer display, not an actual PAL TV could be used.– TrentPJul 7, 2018 at 22:56
-
1@TrentP: The claim (now replaced by a correct statement) was that 720x350 is the resolution of PAL, which is wrong whether you count full frame or half frame resolution.– celtschkJul 8, 2018 at 5:35
-
1The emulator did not necessarily slow down the game if it was not a TSR copying each second line of the triplet to the third line. One of the biggest limitations though was that many CGA applications used to wait for the vertical retrace to avoid snow and that would freeze with an hercules card because it used the 3BA port instead of 3DA. Oh man, was I happy the day I found out I could replace with an hex editor the string BA DA 03 with BA BA 03 to make also these games work!– julodnikNov 13, 2019 at 9:09
The basic idea is to exploit the fact that both CGA and Hercules use the 6845.
I have the source code of an emulator at hand, so I can say what it does:
- it handles the mode-setting function of interrupt 0x10; for all non-Hercules modes, it includes tables of register settings to use to program the Hercules for the appropriate resolution and framebuffer layout;
- it piggy-backs on the timer interrupt to copy the framebuffers when an emulated mode is active (from 0xB800, which is where programs would write when using CGA, to 0xB000, the monochrome buffer).
There are quite a number of different emulators with different levels of success with various programs, so there are no doubt different ways of implementing the emulation.
The limitations are mostly related to hardware handling. Any program writing to the CGA registers won’t work, and any program relying on the Hercules vertical blank interval won’t behave quite right (CGA refreshes at 60Hz, Hercules at 50Hz). The status registers are different too, so polling CGA-style won’t work on Hercules at all. As mentioned by tofro, copying the framebuffers took a noticeable amount of time too (especially on CGA/Hercules-era systems), which would affect the system’s performance.
-
Great explanation, I guess I should more often wait for you to save me work :))– RaffzahnJul 6, 2018 at 12:20
-
1Obviously, moving the framebuffer contents around is not exactly speeding up screen output, especially in graphics modes ...– tofroJul 6, 2018 at 12:20
-
If I correctly remember how the Hercules works, I would think that it should be possible to program the Hercules graphics card to use a "character row" height of 3 rather than 4, and output 80 bytes per line rather than 90. If one did that, set the screen base address to 0xB8000, and erased memory from 0xBC000 to 0xBDFFF, that would yield a 640x300 display mode in which the first two lines of each triplet would match a pair of lines from CGA. The biggest thing I'm unsure about is whether stuff would show up in the right order.– supercatJul 7, 2018 at 17:41
-
1@supercat I wrote a CGA emulator for Hercules at the time, and I used something like this (my memory is hazy) - plus a special TSR that copied the third line, so you could have either (fast) mode where every 3rd line was blank, or a (slower) mode where the 3rd line has been copied from the 2nd one, but this lead to some graphical tearing in moving objects. Still, I was using the TSR even for fast paced games. Jul 9, 2018 at 11:32
-
@RadovanGarabík: I wonder how much it would have cost to change the hardware so that the third scan line in each group could use the same address as the second? I think it could be done with three NAND gates and an mode-select bit, or perhaps with even less hardware.– supercatJul 9, 2018 at 17:16
Just as a correction to a bit of the above: Hercules cards use regular MDA monitors. Their 350-line, nominal 50Hz mode (actually a bit below) isn't anything to do with regular broadcast monitors. They scan at 18.4kHz, which is a good way above that of typical TVs and low-rez monitors at 15.5~15.9kHz (and has the nice side effect of being effectively ultrasonic for most users - no more tube whistle... but a much worse one if you're high frequency sensitive). If you try feeding MDA/Herc syncs into a PAL TV, it could well blow up - and vice versa. Otherwise, there'd be no need for emulation - you could just throw regular CGA signals at it, and it'd work fine. The biggest difference between 50 and 60Hz broadcast monitors is the line count, and plenty of "15kHz" computer monitors can not only vary between those two standards without issue, but also other oddball settings like 45, 56, or 72Hz (with their own greater/intermediate/lesser number of scanlines - the latter having the bare minimum amount of blanking for a 200-line display).
It was, essentially, about as far as IBM were able to custom-tweak the circuitry of a common monochrome video monitor, with a long persistence phosphor on the tube to reduce the flickering effect, without having to go to the expense of a fully re-engineered high frequency item as later used for EGA (which retained much of the scan structure of MDA, but increased the line frequency closer to 22kHz, thus fully ultrasonic, and the Vsync back to 60Hz).
The monitors were somewhat adaptable to different setups, though; there's mention in some manuals for old ATI Wonder graphics cards about their Herc emulation also including the "special" / "little used" custom mode (Herc had NO ROM BIOS, all their modes were setup in software, so the "normal" ones were pretty much just matters of convention, and due to different clock crystals and slightly wonky maths weren't exact matches for the IBM standard anyway) of 640x400. Which was apparently used by some "eastern software" (presumably to better display Japanese/Chinese/Korean script) and wasn't guaranteed to work on all monitors. That mode, of course, would be just dandy for producing a better emulation of CGA, especially the hi-rez monochrome setting, as well as the highest resolution of certain 400-line / 25kHz "super CGA" machines... Unfortunately I have absolutely no idea of its setup, register values etc. The closest I've ever seen is a 90 column by 45 row (720x360 pixel, 8x8 font) textmode, emulated in graphics, which pushes the boundaries of both the available memory and what's displayable on a relatively inflexible MDA.