Marcus Johnson received his B.S. in math from the University of Florida in 1978 and is currently Senior System Engineer for Prericision Software in Clearwater, Florida. You may contact him at 6258 99th Circle, Pinellas Park, Florida.
To self-configure for a user's hardware, your video code must first determine which video adapter is installed. Armed with this knowledge, the video code can determine whether or not color is appropriate (or even possible), how to best execute graphics, whether or not snow is a factor to be dealt with, whether or not the hardware can handle text modes with more than 25 lines, and so on.
The code presented here detects these display adaptor types: Monochrome Display Adaptor (MDA), Color Graphics Adaptor (CGA), Enhanced Graphics Adaptor (EGA), Multi-Color Graphics Array (MCGA), Video Graphics Array (VGA), Hercules Graphics Card, Hercules Graphics Card Plus, and Hercules In Color Card
The code also identifies these display types: MDA-compatible (monochrome), CGA-compatible (color), EGA-compatible (color), PS/2-compatible monochrome, and PS/2-compatible color.
The code presented also detects up to two video hardware systems and distinguishes which is active, and which is not.
Some of these characteristics can't be guaranteed. The assumption of color in the case of CGA and EGA compatible displays is just that, an assumption. The CGA video system has no idea what kind of monitor is attached, and EGA systems can be fooled. Also, there is no way to distinguish for all CGA cards and their clones whether or not the card is prey to the display interference problem of snow. Having discovered that the CGA is present, the programmer must either make an arbitrary decision to allow for snow or ignore its possibility, or have the user make that decision.
The Method
The identification process begins with calls to the enhanced video BIOS; first a call that only a VGA or MCGA equipped system will support, then one that an EGA card should support. These calls will only function with a video BIOS that supports these more sophisticated video systems; CGA, MDA and Hercules cards do not have enhanced video BIOS ROMs, and the calls should fail harmlessly, with all registers preserved. The enhanced BIOS calls will succeed, modifying the registers to identify the installed hardware. If the calls succeed, the job is done, or nearly so; it may be necessary to hunt for a CGA or MDA card of which the more sophisticated video system is unaware.Next the routines attempt to identify the CRT controller (CTRC) status port's address in the PC's I/O space. The MDA and Hercules cards' CRTC status port is usually found at 3B4H, and the CGA cards' CRTC status port at 3D4H. The routines write an arbitrary value to the Cursor Location Low register (0Fh) and then, after a reasonable delay, attempt to read that value back from one of the status port addresses. If the value is recovered, the routines assume they have found the CTRC of the associated card.
In the case of the CGA cards and their clones, there is nothing left to do that's all you can learn. If an MDA card is detected, however, you can also distinguish between an MDA card and the Hercules cards. To do this, the vertical sync bit is sampled and then for a certain time interval, is continually and frequently re-sampled. If no change is observed, the video card is assumed to be an MDA card. If the vertical sync bit changes, the video card is one of the Hercules graphics cards. The specific card is identified by examining bits 4-6 of the status port; a pattern of 001 indicates a Hercules Graphics Card Plus, a pattern of 101 indicates a Hercules In-Color Card, and any other pattern is a Hercules Graphics Card.
Distinguishing CGA from MDA and MDA from Hercules cards are both time-dependent tasks. How much delay is enough to insure the CGA card has had time to update the status port? How frequently must the code sample the vertical sync to ensure it hasn't just missed a transition? Will compiler generated code be fast enough to catch the sync transition at all? If the distinction between the MDA and Hercules cards is important enough, the vertical sync test might best be written in assembly language. In my software, because of these factors, and because I don't usually need to know the difference, I often use a modified version of this code that simply identifies whether or not the system has EGA graphics or better.
In any case, the identification of the video hardware, as with any code that attempts to exploit the hardware environment to its benefit, is not a risk-free undertaking. Even the seemingly straightforward matter of making BIOS calls assumes that the video BIOS will behave in the expected fashion, and in particular that undocumented calls will return with the caller's register values intact. These techniques are very specific to true IBMs. Nevertheless, this and other routines based on [1], have worked on every "100% PC-compatible" I've been able to test.
References
[1] Wilton, Richard, Programmer's Guide to PC and PS/2 Video Systems.This article, and the C source code presented here, are based on Wilton's assembly language version. This excellent reference provides a reasonably complete answer to the problem of detecting and exploiting the video hardware and should be a standard reference for any programmer who wants or needs to know how to milk the PC's video hardware for all it's worth.
main.c
video.h
video.c