Commodore CBM-II computers have rather limited video capabilities – they can only output monochrome 80×25 text. The only PC video hardware that can be reasonably emulated with this is the text-only Monochrome Display Adapter.
The MDA (and its descendant Hercules) is peculiar in that its video buffers are located in a different memory area than all the other PC video cards1. Therefore the applications running on our machine must be convinced that the emulated PC is equipped with a MDA card, otherwise they would write to a wrong video memory area and there would be no screen output. Old applications might also fall into a “CGA death loop”, where they try to prevent “snow” appearing on the screen. To do so, they usually poll a CGA status register in a tight loop waiting for the vertical blanking period which never comes because, well, there is no CGA card in the machine.
And, as it turns out, pretending that we have a MDA card is surprisingly difficult to do.
How it should be done
Officially, a PC application should call INT 11h which returns flags describing various equipment attached to the PC. Among these flags, there is one saying whether the computer has a MDA card or not (and another one saying if it has a CGA card, since these two can be used together).
This way of checking the attached equipment is problematic though. First, in the original IBM PC the returned value was simply read from the jumpers on the mainboard; there’s no way to know if the user set these jumpers properly. Second, the world of graphics cards has grown considerably – now we have EGA, VGA and SVGA cards which are not supported by this BIOS call.
Therefore the actual way to check if the computer has a MDA card (or some other card that emulates the MDA) is to call INT 10h, function 0Fh which returns the current video mode. Mode number 7 is the monochrome MDA text mode, all other modes are CGA, EGA or VGA modes.
How it is actually done
Well, it turns out that instead of using the above simple method, creators of PC applications invented all kinds of “creative” ways to check whether the computer has a MDA card or not. Here are some examples:
- Instead of using INT 11h, read the equipment list from the memory location 0040:0010 where it should be stored in the BIOS data area.
- Instead of using INT 10h, read the actual video mode from the BDA at 0040:0049.
- (this is my personal favorite so far) Try to write something to the 3B5h port (which is the MDA CRTC register value port) and see if the value that is read back matches. This one requires software emulation of the 3B5h register.
I am pretty sure there are other sneaky ways which I haven’t encountered yet, for example reding the CRTC base port from 0040:0063. All of them need to be emulated or the application software will not work.
And by the way, there is also a Hercules death loop as well. Once the application determines that there is a MDA card, it may also want to determine if it’s a plain MDA or a Hercules. But Hercules cards have no BIOS, and to detect them all sorts of I/O port trickery are used. One of them is to poll the MDA status register to see if a bit indicating a video blanking interval changes; to make sure that the whole screen redraw period is covered, this needs to be done a few thousand times. But when every I/O access generates an NMI interrupt which adds at least two orders of magnitude of overhead, this kind of loop would take many minutes to execute. For this reason, the bit in the emulated MDA status register is actually flipping on every access, which unfortunately causes some applications to think that it’s a Hercules. Unfortunately not much can be done about it – there are limits to compatibility that cannot be exceeded.