Artikel

Hercules - VGA - CGA - EGA

Ingo Eickmann

Ob Hercules, ob VGA...

Automatische Erkennung von Videoadaptern

Angesichts der vielen unterschiedlichen Grafikkarten für den PC müssen Programme die Videoausgabe des gerade benutzten Computers eindeutig erkennen, um die Fähigkeiten der jeweiligen Bildschirmdarstellung zu nutzen. Wir zeigen, wie ein Programm den Typ der Grafikkarte erkennt.

Anpassungsfähigkeit ist gefragt. Programme, die sich nicht an die Videoausstattung eines PCs anpassen, sind undenkbar geworden. Um alle Leistungsmerkmale der so unterschiedlich aufgebauten Grafikadapter zu nutzen, fließt nicht nur die maximale Auflösung und die Anzahl der darstellbaren Farben ein: Bei Grafikprogrammen sind schnelle Bildschirmtreiber, die je nach verwendeter Videokarte eingesetzt werden, ein Muß. Erkennt ein Programm ein System mit zwei Bildschirmausgaben, kann die Grafik- und die Textausgabe sogar auf getrennten Anzeigen unabhängig voneinander erfolgen.

Vielfalt an Grafikkarten

Wer als Käufer vor einer schier unüberschaubaren Vielfalt unterschiedlichster Grafikadapter-Monitor-Kombinationen steht, kann sich vorstellen, wie schwer es die Software bei der Unterscheidung hat. Ein Programm sieht schließlich weder die Farbenvielfalt, noch die Auflösung, und trotzdem wird von ihm erwartet, daß es die richtigen Steuerregister korrekt anspricht und die vorhandenen Statusinformationen interpretieren kann.
Im PS/2-Zeitalter wird es für die Software leichter. Das Video-BIOS ist unterhaltsamer geworden und gibt bereitwillig Auskunft über das Videosystem. Doch auch die nach wie vor weit verbreiteten EGA, CGA, MDA und Hercules-Karten müssen unterschieden werden.
Die Fragen, die eine Identifizierungsroutine für Videoadapter beantworten muß, lauten daher:

  • Welche Videoadapter befinden sich im System?
  • Welche Darstellungsmöglichkeiten können genutzt werden?
  • Auf welchem Videoadapter erfolgt zur Zeit die Ausgabe?

Angesichts der unterschiedlichen Grafikadapter kann sich eine allgemeingültige Identifizierung nur auf die Merkmale der Adapterstandards stützen. Die Vielzahl unterschiedlicher Super-EGAs und Super-VGAs und ihre meist nicht detailliert publizierten Erweiterungen zwingen dazu, sie lediglich in ihrer Funktion als Standard-EGA und Standard-VGA zu behandeln. Bild 1 enthält das Flußdiagramm zu einer Identifizierungsroutine. Prinzipiell wird von den bestausgestatteten Adaptern ausgegangen. Erst dann gelangt man zu den Standards CGA und MDA, mit denen die PC-Ära begonnen hat. Zunächst wird die Hardware auf VGA-typische Eigenschaften abgeklopft. Sind diese Eigenschaften nicht vorhanden, handelt es sich nicht um eine VGA, und der nächste Test erfolgt auf eine typische EGA-Eigenschaft. Dabei ist zu beachten, daß EGA-Karten zum VGA-Standard aufwärtskompatibel sind, die EGA-Register und EGA-BIOS-Funktionen sind also als Untermenge im VGA-System enthalten. Die VGA bezeichnet man aus diesem Grund auch als abwärtskompatibel zur EGA.
So wie bei VGA und EGA, verhält es sich zwischen EGA und CGA. Die CGA ist zur EGA – und damit auch zur VGA – aufwärtskompatibel.

Flußdiagramm
Bild 1. Flußdiagramm zu Listing 1: Suchstrategien im Überblick.

Strategie beim Suchen

Das Erkennen des Videoadapters ist in PS/2-Geräten und PCs mit VGA-Karte kein Problem. Das Video-BIOS enthält bei dieser Hardwarevoraussetzung einen Funktionsaufruf, der die vorhandene Ausrüstung als Display Combination Codes liefert. Wenn der Softwareinterrupt 10h eines PS/2-kompatiblen Videosystems mit dem Funktionscode AX=1A00h aufgerufen wird, enthalten nach der Rückkehr das BH- und das BL-Register die Kombinations-Codes des primären und – falls vorhanden – sekundären Videoadapters. Diese Zuordnung erfolgt nach Bit 4 und 5 im Equipment Byte(0040:0010h) und bezieht sich daher auf den Zustand beim Booten. Die Zusammenstellung in Tabelle 1 zeigt alle vordefinierten Kombinations-Codes und die hiermit verbundenen Video-BIOS-Funktionen. Ist diese PS/2-Funktion nicht im Video-BIOS enthalten, besitzt der Computer weder einen VGA, noch einen MCGA-Adapter.
Ist eine EGA-Karte vorhanden, enthält das Video-BIOS die EGA-Funktion Video Subsystem Configuration (AH=12h). Tabelle 2 faßt alle Register zusammen, die für den Aufruf und die Auswertung wichtig sind. Anhand der im CL-Register zurückgegebenen DIP-Switch-Stellungen auf der EGA-Karte läßt sich sofort bestimmen, ob sie als EGA, CGA oder monochromer Adapter konfiguriert wurde. Ist zum Beispiel die Einstellung CGA-Mode gewählt, dann meldet unsere Routine ein CGA-Display.
Wenn keine EGA-Karte gefunden wurde, dann sucht das Programm nach einer CGA. CGA-Karten haben – im Unterschied zu monochromen Adaptern – ihren CRT-Controller 6845 an Port 3D4h/3D5h. Die Anwesenheit des Controllers kann man feststellen, indem man versucht, eines seiner Register über Port 3D4h anzuwählen und über 3D5h zu beschreiben. Den neuen Inhalt liest man wieder aus und verifiziert, ob an dieser Portadresse wirklich ein Register den geschriebenen Wert gespeichert hatte. Nicht vergessen, daß der frühere Registerinhalt gerettet und zum Schluß wiederhergestellt werden muß.
Für diese Art der Überprüfung können jedoch nicht alle Register verwendet werden. Bei den schon fast antiken CGA-Karten sind lediglich die CRTC-Register 14 und 15 (Cursoradresse) sowohl lesbar, als auch beschreibbar.
Wurde auch keine CGA im System erkannt, dann bleibt noch die Möglichkeit, daß ein Monochromadapter vorhanden ist. Ihn kann man auf die gleiche Weise entdecken wie einen Farbgrafikadapter, lediglich die Portadresse des CRT-Controllers ist jetzt eine andere. Monochrome Videoadapter besitzen ebenfalls einen 6845, seine Portadressen sind 3B4h und 3B5h.
Sind alle bisherigen Versuche fehlgeschlagen, einen Videoadapter zu erkennen, dann besitzt der Computer entweder keinen, oder er unterscheidet sich ganz wesentlich von den Standardtypen MDA bis VGA.

Zweit- und Monochromadapter

Mit dem Erkennen einer Videokarte hat das Identifizierprogramm seine Aufgaben aber noch lange nicht erfüllt. Als nächstes muß untersucht werden, ob sich eine zweite Grafikkarte im System befindet. Der PS/2-Funktionsaufruf 1Ah (Video Display Combination) liefert direkt alle installierten Videokarten. Wurde bislang aber nur eine EGA-, CGA- oder MDA-Karte entdeckt, dann müssen wir selbst nach einem eventuell vorhandenen zweiten Adapter suchen. Wenn die EGA als Farbkarte konfiguriert wurde, muß ebenso wie bei einer entdeckten CGA noch nach einer monochromen Karte gesucht werden. Wird die EGA als Monochromadapter eingesetzt, dann kann sich noch eine CGA im PC befinden.
Wann nach welchem Videoadapter gesucht wird, ist anhand des Flußdiagramms ersichtlich. Ergab sich auf diese Weise, daß zwei Videoadapter vorhanden sind (Label Active im Flußdiagramm und im Listing), dann bleibt noch die Reihenfolge zu klären: Auf welchem Bildschirm erscheinen die Standardausgaben des Betriebssystems und welcher Adapter dient lediglich als Sekundärausgabe?
Hier hilft der Videostatus durch den BIOS-Aufruf INT 10h mit ah=0Fh weiter. Auf das Monochromsystem wird nur dann ausgegeben, wenn entweder Videomode 7 (Text) oder 0Fh (Grafik) gewählt ist. In allen anderen Fällen ist der Farbadapter die primäre Ausgabe.
Wenn ein Monochromadapter im System entdeckt wurde, dann muß sowohl bei einem PS/2-Computer, als auch bei einem PC geklärt werden, ob es sich um einen normalen MD-Adapter handelt, oder um eine Hercules-Grafikkarte.
Hierzu ist es sinnvoll, im CRTC-Status-Register (3BAh) das Bit 7 abzufragen. Es enthält nur bei einer Hercules-Karte das vertikale Synchronisationssignal. Bei einer Bildfrequenz von 50 Hz ändert sich der Zustand dieses Bits alle 20 ms für die Dauer des vertikalen Synchronisationspulses. Bleibt diese Änderung aus, dann handelt es sich eindeutig nicht um einen Hercules-Adapter, sondern um einen MDA.
Die Assemblerunterroutine identify in Listing 1, die den Code zum Flußdiagramm in Bild 1 enthält, liefert die Display Combination Codes im AX-Register, AH enthält den Wert für den primären Adapter und AL den Wert für einen sekundären Adapter. Die Zusammenstellung der Kombinations-Codes in Tabelle 1 wurde um den Wert 64 für die Hercules-Karte ergänzt. Das Video-BIOS sah bisher keinen Code für das Nicht-IBM-Produkt von Hercules vor.
Wie die Identifizierung weiterverarbeitet werden kann, zeigen die Listings 2 und 3. Wenn der Objectcode als Funktion eingebunden wird, kann Pascal primäre und sekundäre Ausgabemöglichkeiten erkennen.

Hoch auf OS/2

Mit der Identifizierung des Videosystems ist die Voraussetzung für die Entwicklung portabler Grafiksoftware erfüllt. Jetzt kann eine genauere Untersuchung des Adapters folgen. Bei EGA-kompatiblen Grafikkarten kann beispielsweise die RAM-Ausstattung interessieren, ebenso wie der Zustand der Feature Bits (Tabelle 2).
Die zusätzlich verfügbaren Informationen bei PS/2-Systemen erschlagen einen geradezu. Erwähnt seien an dieser Stelle lediglich die Video-BIOS-Funktionen Video Display Combination (AH=1Ah, Tabelle 1) und Video BIOS Functionality/State Information (AH=1Bh), die einen 64 Byte großen Dynamic Video State Table und einen 16 Byte Static Functionality Table liefert. Genaueres findet sich in weiterführender, spezieller Literatur.
Auf zwei Unzulänglichkeiten des PS/2-Interrupts beim Model 30 muß der Vollständigkeit halber hingewiesen werden. Ist im Model 30 eine VGA installiert, dann wird der vorhandene MCGA-Adapter nicht mehr erkannt. Abhilfe: Model 30 am BIOS-Identifikationsbyte (FFFF:000Eh) erkennen und automatisch MCGA melden.
Ist dagegen zusätzlich eine EGA-Karte eingesteckt, dann wird nur der MCGA-Adapter gemeldet. Wenn das Model 30 erkannt wurde, können wir die EGA-Karte mit der EGA-BIOS-Funktion aus Tabelle 2 erkennen. Wer selbst auf diese Fälle noch eingehen möchte, kann das Flußdiagramm und den Code leicht ergänzen.

Erkennen von Monitoren

Ein Glied in der Funktionskette Computer-Videoadapter-Monitor-Mensch bleibt der Software aber unbekannt: Der Monitor. Er bestimmt letztendlich, wie das Bild dem Menschen dargeboten wird.
Ginge es nach dem Willen von Big Blue, dann gäbe es seit der Markteinführung der PS/2-Modelle nur noch Monitore (und Monitorkabel), die dem VGA-System über die drei codierten Monitor-Kennungsbits verraten, wie der jeweilige Monitor angesteuert werden will und welche Betriebsarten er zuläßt. Noch ist die Masse der Monitore und Monitorkabel hierzu jedoch nicht in der Lage. Das hat viele Designer von VGA-Clones wohl dazu bewogen, auf eine automatische Verarbeitung der Kennungsbits zu verzichten und die altbekannten DIP-Schalter noch nicht in der untersten Schublade verschwinden zu lassen.
Nach wie vor ist es bei vielen Nachbau-VGA, ebenso wie bei allen Adaptervorgängern nicht möglich, softwareseitig die Ausgabe eines farbigen Bildes auf einem monochromen Monitor zu erkennen und selbständig auf ein Videolayout für monochromes Anzeigen umzuschalten.
Die einheitliche Codierung von Monitoren läßt sich sicher nur durch die Publizierung des Codierungssystems erreichen, was zusammen mit der Einführung des neuen 15poligen Videosteckers bereits den Durchbruch hin zu einer einheitlichen Monitorcodierung hätte bringen können.
Der Monitor bleibt die einzige Schwachstelle bei der Erkennung der Bildausgabe auf einem Videoschirm.

Tabelle 1. PS/2 Video Display
Return Video Display Combination:
Aufruf:
al =
0
Rückgabe:
al =
1Ah
bh =
primärer Adapter beim Booten
bl =
sekundärer Adapter beim Booten

Folgende Werte sind definiert:
-1:
nicht erkannt
0:
nicht vorhande
1:
Monochrome Display Adapter (MDA)
2:
Color Graphics Adapter (CGA)
3,9:
reservierter Code
4:
Enhanced Graphics Adapter (EGA) im Color Mode
5:
Enhanced Graphics Adapter (EGA) im Monochrome Mode
6:
Professional Graphics Controller
7:
Video Graphics Array (VGA) mit Monochrome Display
8:
Video Graphics Array (VGA) mit Color Display
10:
Multi-Color Graphics Array (MCGA) mit digitalem Color Display
11:
Multi-Color Graphics Array (MCGA) mit analogem Monochrome Display
12:
Multi-Color Graphics Array (MCGA) mit analogem Color Display

Set Video Display Combination:
Aufruf:
al =
1
bl =
primärer Adapter
bh =
sekundärer Adapter
Rückgabe:
al =
1Ah, wenn die gewählten Display Combination Codes bei
den installierten Adaptern möglich sind.

Alle bei der jeweiligen Hardware möglichen Wertepaare für bh und bl sind im
Display Combination Code Table verzeichnet. Auf seinen Anfang zeigt der
zweite Vektor des Secondary Save Pointer tables.
Der Display Combination Code Table Index (DCC, 0040:008Ah) zeigt auf die
gewählte Adapterkombination im Display Combination Code Table, der
folgendermaßen aufgebaut ist:

1.Byte:
Anzahl der Einträge im Datenfeld
2.Byte:
Display Combination Code Table Version
3.Byte:
Maximale Adapterkennzahl
4.Byte:
reserviert
5.Byte:
Hier beginnt das Datenfeld mit allen möglichen Combination Codes.
Der DDC zeigt auf die gerade angewählte Kombination.

Tabelle 2. EGA Video Subsystem
Return Video Configuration Information:
Aufruf:
bl =
10h
Rückgabe:
bh =
default BIOS-Videomode
(0: Color, 1: Monochrome)
bl =
Größe des Video RAM
(0: 64 KByte, 1: 128 KByte,
 2: 192 KByte, 3: 256 KByte)
ch =
Feature Bits
cl =
Stellung der Konfigurationsschalter

Listing 1. Identifizierung von Grafikadaptern
;------------------------------------------------------------------------
;     Identifizierung von Video Adaptern                      release 1.0
;     Copyright (c) Ingo Eickmann, 1989                          09/01/89
;------------------------------------------------------------------------
      PAGE   65,80
      TITLE  Identify

code  segment word public 'CODE'
      assume cs:code
;------------------------------------------------------------------------
;                                       Identifizierung von Videoadaptern
public Identify                       ; Rückgabe: AH: primärer Adapter
;                                                 AL: sekundärer Adapter
;------------------------------------------------------------------------
Identify proc far
        mov  ax,1A00h
        int  10h                      ; PS/2 Video Display Combination
        cmp  al,1Ah                   ; PS/2 ?
        je   Active                   ;   Ja ->
        mov  ah,12h
        mov  bl,10h
        int  10h                      ; EGA Video Subsystem Configuration
        cmp  bl,10h                   ; EGA vorhanden ?
        mov  bx,0
        je   TestCGA                  ;   Nein ->
        mov  al,cl
        shr  al,1                     ; DIP-Schalterstellung umrechnen
        cmp  al,3
        jl   EGA1
        sub  al,3
EGA1:   mov  bh,2
        jz   TestMDA                  ;   EGA als CGA ->
        shl  bh,1
        cmp  al,1
        je   TestMDA                  ;   EGA als EGA ->
        mov  bh,5                     ; EGA als monochromer Adapter
        call CGA                      ; CGA vorhanden ?
        jnc  Active                   ;   Nein ->
        mov  bl,2
        jmp  Active
TestCGA:
        call CGA                      ; CGA vorhanden ?
        jnc  TestMDA                  ;   Nein ->
        mov  bh,2
TestMDA:
        call MDA                      ; MDA vorhanden ?
        jnc  Active                   ;   Nein ->
        mov  bl,1
        or   bh,bh
        jnz  Active
        xchg bh,bl
Active:
        or   bl,bl                    ; Adapter 2 gefunden ?
        jz   TestHerc                 ;   Nein ->
        push bx
        mov  ah,0Fh
        int  10h                      ; Return current Video Status
        pop  bx
        and  al,7
        cmp  bh,1                     ; Adapter 1 MDA oder EGAMono ?
        je   Mono
        cmp  bh,5
        jne  NotMono                  ;   Nein ->
Mono:   cmp  al,7                     ; Mono Mode ?
        je   TestHerc                 ;   Ja -> Reihenfolge stimmt
        jmp  Tausch
NotMono:                              ; Adapter 1 ist Color
        cmp  al,7                     ; Mono Mode ?
        jne  TestHerc                 ;   Nein -> Reihenfolge stimmt
Tausch: xchg bh,bl                    ; Adapter 1 <-> Adapter 2
TestHerc:
        cmp  bh,1                     ; Adapter 1 = MDA ?
        jne  Herc1                    ;   Nein ->
        call Herc                     ; Ist monochromer Adapter Hercules ?
        jnc  Raus                     ;   Nein ->
        mov  bh,64                    ; Hercules Display Combination Code
Herc1:  cmp  bl,1                     ; Adapter 2 = MDA ?
        jne  Raus                     ;   Nein ->
        call Herc                     ; Ist monochromer Adapter Hercules ?
        jnc  Raus                     ;   Nein ->
        mov  bl,64                    ; Hercules Display Combination Code
Raus:   mov  ax,bx
        ret
Identify endp

;------------------------------------------------------------------------
; CGA: Carry gesetzt, wenn 6845 einer CGA gefunden
;------------------------------------------------------------------------
CGA proc near
        mov  dx,3D4h                  ; CRT Controller Adresse bei CGA
        call Test6845                 ; 6845 vorhanden ?
        ret
CGA endp

;------------------------------------------------------------------------
; MDA: Carry gesetzt, wenn 6845 eines MDA gefunden
;------------------------------------------------------------------------
MDA proc near
        mov  dx,3B4h                  ; CRT Controller Adresse bei MDA
        call Test6845                 ; 6845 vorhanden ?
        ret
MDA endp

;------------------------------------------------------------------------
; Herc: Carry gesetzt, wenn monochromer Adapter als Hercules erkannt
;------------------------------------------------------------------------
Herc proc near
        mov  dx,3BAh                  ; CRTC Status Register
        in   al,dx                    ; Bit 7: Vertical Synchronisation
        and  al,10000000b             ;        (etwa alle 20 msec)
        mov  ah,al
        xor  cx,cx
Lop:    in   al,dx                    ; Warteschleife bis zur nächsten
        and  al,10000000b             ; Änderung
        cmp  ah,al
        loope Lop
        clc
        je   NoHerc                   ;   keine Änderung des Bits ->
        cmc                           ; Änderung war da: Hercules
NoHerc: ret
Herc endp

;------------------------------------------------------------------------
; Test6845: Carry gesetzt, wenn 6845 an Port [dx] erkannt
;------------------------------------------------------------------------
Test6845 proc near
        mov  ax,01F0Eh                ; Cursor Start Position
        out  dx,al
        inc  dx
        in   al,dx                    ; alten Inhalt retten
        xchg ah,al
        out  dx,al                    ; neuen Wert schreiben
        mov  cx,100
        loop $
        in   al,dx                    ; neuen Wert wieder auslesen
        xchg ah,al
        out  dx,al                    ; alten Inhalt zurückschreiben
        cmp  ah,01Fh
        clc
        jne  No6845                   ; war ein CRTC Register vorhanden ?
        cmc                           ;   -> Ja: Carry setzen
No6845: ret
Test6845 endp

code ends
     end

 

Listing 2. Einbindung in Turbo Pascal
unit Iden;

(* Unit - Deklaration für Turbo Pascal 4.0/5.x, I.Eickmann 1989 *)

{$F+}

interface
  function Identify : integer;

implementation
  {$L IDENTIFY.obj}
  function Identify; external;

end.

 

Listing 3. Offenlegung der Videoausstattung
program Videoadapter;

(* Identifizierung des primären/sekundären Videoadapters, I.Eickmann 1989 *)

uses Iden;

var  Video1,Video2 : Integer;

procedure printAdapter(Video : Integer);

var str : string;

beginHEIGHT=22
  case Video of
    0:   str := 'nicht vorhanden';
    1:   str := 'Monochrome Display Adapter (MDA)';
    2:   str := 'Color Graphics Adapter (CGA)';
    3,9: str := '[reservierter Video Display Combination Code (DCC)]';
    4:   str := 'Enhanced Graphics Adapter (EGA) im Color Mode';
    5:   str := 'Enhanced Graphics Adapter (EGA) im Monochrome Mode';
    6:   str := 'Professional Graphics Controller';
    7:   str := 'Video Graphics Array (VGA) mit Monochrome Display';
    8:   str := 'Video Graphics Array (VGA) mit Color Display';
    10:  str := 'Multi-Color Graphics Array (MCGA) ' +
                'mit digitalem Color Display';
    11:  str := 'Multi-Color Graphics Array (MCGA) ' +
                'mit analogem Monochrome Display';
    12:  str := 'Multi-Color Graphics Array (MCGA) ' +
                'mit analogem Color Display';
    64:  str := 'Hercules Graphics Card (HGC)';
    else str := 'nicht erkannt';
  end;
  writeln(str);
end;

Begin
  Video1 := Identify;
  Video2 := Video1 and 255;
  Video1 := Video1 shr 8;

  write('Videoadapter 1: ');
  printAdapter(Video1);

  write('Videoadapter 2: ');
  printAdapter(Video2);
End.

 

aus mc 05/90 – Seite 44-48