16

I am trying to programatically detect the CGA card on old IBM 5150-ish PCs.

The Paku Paku game source code doesn't directly detect it. The strategy is to detect VGA, EGA, Tandy, PCJr, etc etc, then if none of those "hit", assume it is CGA. Similar code is found here: https://forum.vcfed.org/index.php?threads/is-there-a-way-to-detect-a-plantronics-colorplus-card-by-software.79115/ and here: https://www.brutman.com/forums/viewtopic.php?t=119

However I'm wondering if there is some way to directly detect the CGA card's presence?

I realize the IBM BIOS source code may have references to this but I'm not sure of exactly how it's doing it so I kind of gave up looking at that. I know that it's detecting between no video, MDA, and CGA, but I'm not sure if that is compatible with technology that did not exist when the BIOS was written. (Edit - please see Raffzahn's answer below, BIOS is not doing what i thought!!!)

The guide at http://www.tinyvga.com/6845 regarding the Motorola shows that most of the registers in the CGA's Motorola 6845 chip are write only, however the cursor addresses at registers 14 and 15 are both read/write.

I am wondering if I output data to register 14 at the 6845 I/O-portaddress, and read it back, using x86 OUT and IN instructions, would that be good evidence the machine had a CGA card?

What happens if you write to an I/O-port that doesn't exist in the hardware? Does it crash?

don bright
  • 465
  • 2
  • 12
  • Would it be possible to attempt to activate CGA mode via the BIOS routine, plot a pixel, and then check that the appropriate data has been written to the correct location in video RAM? – Tim Locke May 04 '23 at 01:59
  • i feel like VGA cards would just emulate the bios modes and i wouldnt be able to tell fake from real......... i realize as i write this, might have the same problem with 6845. – don bright May 04 '23 at 03:03
  • 2
    Other graphics card all emulated CGA to some degree. You'd have to find something that was NOT emulated by other graphic cards which is unique to CGA to make sure that it's a CGA and not some other card. And yes, you can check for the presence of 6845 registers to verify that the PC has a graphics card at all (but this is not a useful check, nobody was going to run a game on a PC without any graphics...) – dirkt May 04 '23 at 03:41
  • @TimLocke That only shows that there (might) be some RAM at that location – Raffzahn May 04 '23 at 05:23
  • 1
    @dirkt All video cards have to bring their own INT 10h handler in form of a BIOS expansion ROM. BIOS only includes handlers for CGA and MDA (as set by switches). Everything else is ignored. Compatibility is handled by those expansion ROM providing the same INT 10h functions as the BIOS would do for CGA/MDA. – Raffzahn May 04 '23 at 05:25
  • 2
    @Raffzahn There were plenty of applications which completely ignored the BIOS, so compatibility is handled on the hardware level. You can find this even on post-VGA cards, that all simulate earlier cards, complete with the slow access via IN/OUT (while also providing PCI memory mapped registers), and sprinkling the extension bits across various CRTC indices. However, you may be able to detect a CGA ROM, though I don't know how many versions the ROM went through. – dirkt May 04 '23 at 06:08
  • 2
    @dirkt What CGA ROM would you detect, and how? – Justme May 04 '23 at 06:22
  • 2
    @dirkt CGA (and MDA) does not have a ROM. Also the fact, that some later cards may be (in part) compatible doesn't change that. I just went thru the process of supporting the creation of a new compatible XT BIOS over the last year or so. – Raffzahn May 04 '23 at 06:52
  • 1
    Well, technically the CGA and MDA do have ROMs, but they're not addressable by the host PC's CPU so wouldn't be relevant to card detection. – john_e May 04 '23 at 07:13
  • @Raffzahn, I was thinking a CGA pixel might look different in memory from an EGA or VGA pixel. – Tim Locke May 04 '23 at 13:32
  • 1
    @TimLocke: The CGA font ROM sits on a one-way data path between the RAM data bus and row couinters, a shifter, some multiplexing circuitry, and the monitor output. If one were to run a wire from the monitor red and green output to e.g. a couple of game port button inputs, it might be possible to write some code which could analyze some things about the CGA's ROM content, but absent such external connection there is no path from the ROM back to the CPU. – supercat May 04 '23 at 14:48
  • @supercat, Is the CGA video RAM at B8000 not readable? – Tim Locke May 04 '23 at 18:43
  • 2
    @TimLocke It is. But it only ever contains stuff written there by CPU. In text mode it contains character codes and attributes. In graphics mode it contains pixels. So the pixels, if they represent pixels of font, is written by CPU via BIOS or user code. You can read the RAM, you can't access the text mode font ROM, because that's the hardware that converts character codes to pixels of a character. – Justme May 04 '23 at 20:43
  • @Justme, why would I want to read the font ROM? I never said I wanted to. Supercat was talking about the font ROM. I just want to write a pixel there and then check the RAM to see whether what I wrote is there. If it doesn't match, then it's not CGA mode. – Tim Locke May 04 '23 at 21:00
  • 2
    @TimLocke: Ah--I thought you were wanting to see what was being output to distinguish between a CGA card and various clones thereof, in which case being able to see the output pixel stream could occasionally be useful if it were possible. – supercat May 04 '23 at 21:46
  • 1
    @TimLocke That won't test if you have a CGA. It just tests if there is any memory or memory mapped device which you can write and read back the same value, but it may be something else than a CGA. – Justme May 04 '23 at 21:47
  • No, I mean use the BIOS to switch to CGA, then directly read from CGA RAM, then write a pixel using the BIOS routine, and directly read from CGA RAM again. If the RAM changed, it's in CGA RAM. I just wrote a program to do this and writing a pixel to 0,0 via the BIOS routine changes the first byte in the CGA RAM. – Tim Locke May 04 '23 at 22:06
  • 1
    @TimLocke I'd have to check how that would work, but it the BIOS checks for CGA presence before setting up a mode, it would fail to set the mode so you don't need to do the pixel check. If BIOS does not care about CGA being present, it can blindly allow you to change modes and write pixels via BIOS. If pixels don't match then you have no CGA, but if they match, it might mean you have some other device like network adapter or EMM card at address b8000h and it gives a false result. While it can be used as a simple check, it does not check CGA reliably. – Justme May 05 '23 at 04:48

4 Answers4

21

You can, in fact, relatively reliably and safe, detect a 6845 in your system by trying to write to a 6845 register and see whether you can read back the same value. I have successfully done that with the "Cursor End" register - an action that is easily reversible and relatively non-destructive. Use the address register at 0x3D4 to write the register number, then the data register (one up) to write your value - wait a short time, then try to read back from the data register using the same method. If you can read the same value, you're relatively safe to assume you have a 6845 in the system. After that, restore the old "Cursor End" value you hopefully saved before.

(You can use the same method to detect MDA and Hercules cards at 0x3b4. It is, however, a bit more tricky to distinguish between these two)

Note, however, that for a dual-card setup (MDA+CGA), the pure existence of a 6845 at the CGA port address doesn't necessarily mean that this display adapter is in fact the active one currently - You'd still use the BIOS (or "DIP switch") settings to detect which one is the currently active adapter.

Also, you might want to do the VGA and EGA tests before (I use the video BIOS to do that), otherwise you might mis-treat one of those in CGA mode as a "real" CGA adapter.

Toby Speight
  • 1,611
  • 14
  • 31
tofro
  • 34,832
  • 4
  • 89
  • 170
  • 1
    Note that currently available adapter doesn't mean the other doesn't work. Long ago I wrote code that simultaneously used the CGA for text and the VGA(?) for graphics. Over time fewer cards would play nice with coexistence and it finally became necessary to simply copy out the initialization code and then do everything directly. – Loren Pechtel May 07 '23 at 04:02
  • @LorenPechtel Of course. When the adapter is detectable, it will most probably work - But your program needs to have a strategy what it wants to do with more than one available character and cannot simply assume a monitor is connected and the whole chain is operable. I Have, however, yet to find a situation where there is MDA and CGA in a system and not interoperable. – tofro May 07 '23 at 07:04
  • In my case I was free to simply fail if the required hardware wasn't present--this was in-house software, the two-monitor mode used by roughly a dozen people. – Loren Pechtel May 08 '23 at 02:42
  • Apparently this was hard back then too, so many games just asked what the user would like. Civilization 1: https://i.stack.imgur.com/liPOw.png – Thorbjørn Ravn Andersen May 09 '23 at 05:11
  • @ThorbjørnRavnAndersen It wasn't any harder back then than it is today, but sometimes people tend to be lazy. The example screen shows a selection between VGA, EGA and MCGA - These have always been easy to detect using the video BIOS, Tandies and PCjr a bit harder. The point is rather how software was delivered to the end customer: New "standards" were coming up any week, and it was a lot easier to have your phone support tell people to use this or that selection in a menu than to re-copy thousands of floppies with a new detection routine and distribute via mail. – tofro May 09 '23 at 07:59
  • @tofro I don't know why they did this, but they let the user choose. – Thorbjørn Ravn Andersen May 09 '23 at 08:00
  • @ThorbjørnRavnAndersen That's what I'm saying: They let the user choose because that was the easiest way to be able to override a faulty or incomplete (or, outdated by technology development) detection routine. Maybe the ideal way would have been to offer to change a detected default like "we detected CGA, but if you know better, select what you think". – tofro May 09 '23 at 08:29
11

The Paku Paku game source code doesn't directly detect it. The strategy is to detect VGA, EGA, Tandy, PCJr, etc etc, then if none of those "hit", assume it is CGA.

Does it, or would MDA also be supported?

In any case it's the way conforming to the PC's design.

I realize the IBM BIOS source code may have references to this but I'm not sure of exactly how it's doing it so I kind of gave up looking at that.

(Genuine) PC/XT BIOS does not do such at all. It's from the good old times of reliable configuration values stored in manual switches. All those complicated probings are later inventions. BIOS simply looks for all hardware configuration at the motherboard configuration switches, in this case Switch Block 1 (SW1).

While those no longer physically exist, all later PC compatible hardware emulates them from some BIOS setting.

I know that it's detecting between no video, MDA, and CGA, but I'm not sure if that is compatible with technology that did not exist when the BIOS was written.

In this case it's switch 5 & 6 of SW1 as MinusZeroDegree tells:

Video card type.
5=OFF, 6=OFF:    MDA (monochrome)
5=OFF, 6=ON :    CGA, at 40 column by 25 line mode
5=ON , 6=OFF:    CGA, at 80 column by 25 line mode
5=ON , 6=ON :    Cards with a BIOS expansion ROM (e.g.  EGA / VGA)

BIOS assumes that only that selected card is fitted and ignores everything else. Also ON/ON setting is not usable for PC's with BIOS prior to 10/27/82, as it was that version that first scanned for extension ROMs.

Basically the BIOS itself uses INT 10h (Video output) for all output but only installs INT 10h handlers for CGA or MDA. Everything else relies on BIOS expansion ROM being present and installing their own video output handlers.

Plug and Play as it was intended.

What happens if you write to an I/O-port that doesn't exist in the hardware? Does it crash?

Usually not (*1). A read will return random values, mostly defined by bus load/capacity. A write will simply do nothing - or a least it should :))

--

*1 - Some non-IBM PC hardware may execute a bus fault.

Raffzahn
  • 222,541
  • 22
  • 631
  • 918
  • 1
    wow thats awesome, thank you for posting that. i had completely forgotten about dip switches on motherboards, probably been 20 years since i touched one.. . – don bright May 05 '23 at 02:00
11

If all the other adapters have already been detected to be absent from the system, the possible options are that there are no MDA or CGA adapter at all, there is either MDA or CGA adapter installed, or there are both MDA and CGA adapters are installed. In this case the BIOS simply uses which is selected by the user.

The CGA and MDA adapters live in different IO and memory addresses that don't overlap, so while they both can be present in the system, only one can be the default which the BIOS uses for output.

I recall that one BIOS seemed to blindly initialize both cards without checking their presence, and then used the one that's set to default. That's because it is preferable to initialize the video output properly, as if some user program has programmed the output incorrectly, pressing ctrl-alt-del does not cause a hardware reset to reset the MC6845 CRTC to stop video output.

The idea of using the cursor address register of MC6845 should be a valid option to probe the presence of a CGA adapter, from the CGA port address 3D4h/3D5h.

Another way is to poll the CGA status register 3DAh for proper looking signals. The bit 0 contains an active low Display Enable signal, and bit 3 has the Vertical Sync. Bit 2 should be high on an original CGA adapter when light pen trigger is not pushed. Bit 1 being high means light pen event has been triggered and if it is set, the bit can be cleared by writing to port 3DBh. The VSYNC should go high briefly at 59.9 Hz rate, and the DE should go low during each of the 200 active lines per frame at rate of 15.7 kHz and be high otherwise between lines and frames.

Bruce Abbott
  • 6,673
  • 15
  • 31
Justme
  • 31,506
  • 1
  • 73
  • 145
  • 1
    Disabling interrupts and measuring horizontal and vertical sync rates would make it possible to distinguish a variety of CGA clones, especially if one were to modify the values of some CRTC registers and observe the effects thereof. – supercat May 04 '23 at 14:52
  • 1
    @supercat On a classic PC, you have a minimum granularity of 18.2ms to measure time - That's by far not enough to measure sync times. You could base your measurement on the CPU clock, but then, well, it's based on the CPU clock. YOu could re-program the PIT, but then again, that would only work on relatively compatible machines. All in all, way too much hassle. – tofro May 08 '23 at 07:58
  • 1
    @tofro On a classic PC the PIT is just programmed to slowest possible divisor of 65536 (0) to get interrupts at 18.2 Hz rate. The PIT still runs at count rate of 1193181.8 MHz and it can be reprogrammed with any divisor you like, or the counter register can be read for timestamps at the count rate. – Justme May 08 '23 at 08:57
  • 1
    @tofro: Even without reprogramming the PIT, waiting for a PIT count, and then counting the number of horizontal blanks until the next sync along with the minimum and maximum numbers of horizontal blanks within vertical high and low intervals should make it possible to distinguish among the common video sync rates even if there might be a few missed horizontal blanks. – supercat May 08 '23 at 14:50
1

To answer the specific question:

What happens if you write to an I/O-port that doesn't exist in the hardware? Does it crash?

That doesn't happen with any Intel or Zilog microprocessor I'm aware of. When you write to a port, the address, data and control lines are set appropriately and it's up to the hardware to notice that its address is selected and route the data into the peripheral. If we write to a port where no hardware is listening, then the data bus is not routed anywhere, and the write has no effect.

A similar principle applies to memory operations - a write to an address not backed by real memory will have no effect, and a read will give the result of interpreting an unasserted data bus (often all ones or all zeros, but possibly just random data, depending on the logic family).

On the other hand, writing to a port that does have corresponding hardware, but isn't the hardware you expected, may have almost any outcome, up to and including physical damage. So be careful!

Toby Speight
  • 1,611
  • 14
  • 31
  • 2
    You only need to consider the Motorola M68000 CPU for that. It has a DTACK pin which is required to terminate a bus cycle. If there is no memory or device to acknowledge the bus cycle, it will wait forever. Although your motherboard could have a system to terminate the cycle with an error if it does not happen within a sensible time. Also on certain SoundBlaster cards that don't have sockets for the CMS/GameBlaster chips but they are not present, writing to the chips will cause logic on the sound card to add wait states until the chip signals it's ready, and that never happens. – Justme May 10 '23 at 12:51
  • 1
    Thanks @Justme. I've only done software on a M86k, so I've edited to reflect the limits of my knowledge. – Toby Speight May 10 '23 at 13:12