VGA 16 Color Modi-Programmierung

Diskussion zum Thema Programmierung unter DOS (Intel x86)
Antworten
Brueggi

VGA 16 Color Modi-Programmierung

Beitrag von Brueggi »

So, ich wende mich mal an die zahlreichen Freaks hier. Es geht um die Programmierung der 16-Farb-Modi, genauer um 640x480 einer VGA-Karte. Es interessiert vielleicht auch andere. Wie genau programmiere ich denn diesen modus? Ich hab mal gelesen, es gibt ein Latch-Register, mit dem man die "Planes" auswählt, auf welche man zugreift.

Wie sieht das in der Praxis aus? Welche Tricks gibt es, das ggf. zu beschleunigen? Vielleicht könnte man hier mal eine Art Tutorial zusammentragen, über das Einschalten der Grafik bis zum Setzen von Punkten usw. Ich habe schon im PC-Intern gelesen aber das kapier ich nicht so recht. Da geht das irgendwie "durcheinander" bzw. ohne Register-Bezüge.

Vielen Dank schonmal im Voraus für Eure Hilfe.
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: VGA 16 Color Modi-Programmierung

Beitrag von freecrac »

Brueggi hat geschrieben:So, ich wende mich mal an die zahlreichen Freaks hier. Es geht um die Programmierung der 16-Farb-Modi, genauer um 640x480 einer VGA-Karte. Es interessiert vielleicht auch andere. Wie genau programmiere ich denn diesen modus? Ich hab mal gelesen, es gibt ein Latch-Register, mit dem man die "Planes" auswählt, auf welche man zugreift.

Wie sieht das in der Praxis aus? Welche Tricks gibt es, das ggf. zu beschleunigen? Vielleicht könnte man hier mal eine Art Tutorial zusammentragen, über das Einschalten der Grafik bis zum Setzen von Punkten usw. Ich habe schon im PC-Intern gelesen aber das kapier ich nicht so recht. Da geht das irgendwie "durcheinander" bzw. ohne Register-Bezüge.

Vielen Dank schonmal im Voraus für Eure Hilfe.
Am Anfang wusste ich es noch nicht wie einfach alle anderen Grafikmodi zu verwenden sind.
Hätte ich das schon gewusst, dann hätte ich niemals damit anfangen wollen 16 Farb-Modi zu verwenden.
So habe ich mich aber doch damit durchgequält und erst danach andere Videomodi ausprobiert.
Das ist auch schon eine Weile her und gut erklären kann ich es wohl auch nicht.
Für jeden Pixel muss ein Portzugriff gemacht werden und ein Dummyzugriff.

Hier ist ein Pixelsetzer für verschiedene 16 Farben Modi und mit Bankumschaltung für ET4000 bei SVGA.

Code: Alles auswählen

;┌───────────────────────────────────────────────────────────────────┐
;│                      P I X E L  -  S E T Z E R                    │
;└───────────────────────────────────────────────────────────────────┘
PIXEL:    pusha
          add    bp, XMIN
          add    bx, YMIN
          mov    cx, bp              ; Bildschirm-Offset
          shr    cx, 3
          mov    ax, PS              ; Anzahl Pixel pro Zeile
          mul    bx                  ;    * Y
          add    ax, cx              ;        + (X/8)
          mov    di, ax              ;                = Adresse
          cmp   BYTE PTR[FLAG_2], 5  ; SVGA ?
          jb  VGA
          mov    al, dl              ; Bankumschaltung ET4000
          shl    al, 4               ; bei SVGA: 1024x768 und 1280x1024
          add    al, dl              ; Ueberlauf 64K Grenze
          mov    dx, 3CDh       ; Portadresse für ET4000 Bankumschaltung
          out    dx, al
VGA:      inc    cx                  ; Bit (Pixel) berechnen !
          shl    cx, 3
          sub    cx, bp
          dec    cx
          mov    ah, 1               ; 2 ^ (((X/8) + 1) * 8 - X) - 1
          shl    ah, cl              ;                      = Pixel pos.
          mov    dx, 3CEh            ; Pixel-Mask-Register
          mov    al, 8
          out    dx, ax
          mov    al, fs:[di]         ; Dummy-READ (Adresse holen)
EBENE:    mov   BYTE PTR fs:[di], 1  ; Pixel setzen
          popa
          ret
Verschiedene Unter-Routinen zum Wechseln von 16 Farben Videomodi für ET4000:

Code: Alles auswählen

SCHALTE:  mov    ax, 0Dh           ; schaltet in den ausgewählten Video-Mode│
          int  10h                 ;────────────────────────────────────────┘
          mov   WORD PTR[PS], 28h  ; 16 / 320 x  200  A000
          mov  DWORD PTR[ZEUG], 00020000h  ; Verzögerungs Index
          ret                      ;
modelen  =  ($-SCHALTE)            ;-----------------------------------------

          mov    ax, 0Eh           ; 16 / 640 x  200  A000
          int  10h                 ;   
          mov   WORD PTR[PS], 50h  ;
          mov  DWORD PTR[ZEUG], 00018000h  ; Verzögerungs Index
          ret                      ;-----------------------------------------

          mov    ax, 10h           ; 16 / 640 x  350  A000
          int  10h                 ;
          mov   WORD PTR[PS], 50h  ;
          mov  DWORD PTR[ZEUG], 00010000h   ; Verzögerungs Index
          ret                      ;-----------------------------------------

          mov    ax, 12h           ; 16 / 640 x  480  A000
          int  10h                 ;
          mov   WORD PTR[PS], 50h  ;
          mov  DWORD PTR[ZEUG], 00008000h  ; Verzögerungs Index
          ret                      ;-----------------------------------------

          mov    ax, 29h           ; 16/ 800 x  600  A000
          int  10h                 ;54h=ATIWOND /6Ah=CHIP&TE/VEGA/ZYMOS/VESA
          mov   WORD PTR[PS], 64h  ;79h=GENOA  /58h=PARADIS/WESTERN DIGITAL
          mov  DWORD PTR[ZEUG], 00000001h  ; Verzögerungs Index
          ret                      ;-----------------------------------------

          mov    ax, 37h           ; 16/ 1024 x  786 A000
          int  10h                 ;55h=ATI       / 18h=TECMAR
          mov   WORD PTR[PS], 80h  ;72h=CHIP&TECH/ 37h=TSENG/ORCHID/SIGMA
          mov  DWORD PTR[ZEUG], 00000001h  ; Verzögerungs Index
          ret                      ;-----------------------------------------

          mov    ax, 3Dh           ;  16 / 1280 x 1024 A000
          int  10h                 ;03Dh = TSENG / ORCHID / SIGMA
          mov   WORD PTR[PS], 100h ;106h = VESA
          mov  DWORD PTR[ZEUG], 00000001h  ; Verzögerungs Index
          mov    dx, 3D4h          ;ET4000:Rasterzeilen fuer Bankgrenzen
          mov    ax, 8013h         ;   Wert/2 im 16 Farbmodus
          out    dx, ax            ;Alt=160 Bytes je Zeile = X/8 Pixel
          ret                      ;Neu=256 Bytes je Zeile = X/8 Pixel
Programmiert für einen Intel 80386 @40mhz mit ET4000 kann man das ganze in einem schlichten Grafik-Demo, wo ein paar Linen gezeichnet werden sich ansehen. Vorher kann man in einem Menü u.A. eine von den folgenden Auflösungen dafür ausgewählt werden.

┌───────┐
│ M a t r i x │
├───────┤
│ 320 x 200 │
│ 640 x 200 │
│ 640 x 350 │
│ 640 x 480 │
│ 800 x 600 │
│ 1024 x 768 │
│ 1280 x 1024 │
└────────┘

http://www.alice-dsl.net/freecracmaps/Tool/Quix96.zip

Wie schon erwänht das Demo ist für einen 80386 mit 40 mhz. Bei schnelleren CPUs wird im Menü der Cursorbalken wohl zu schnell durchlaufen, um das Menüs mit den fix eingestellten Verzögerung-Werten dafür noch sinnvoll benutzen zu können.

Dirk
wobo
DOS-Guru
Beiträge: 613
Registriert: So 17. Okt 2010, 14:40

Re: VGA 16 Color Modi-Programmierung

Beitrag von wobo »

freecrac hat geschrieben:
Am Anfang wusste ich es noch nicht wie einfach alle anderen Grafikmodi zu verwenden sind.
Hätte ich das schon gewusst, dann hätte ich niemals damit anfangen wollen 16 Farb-Modi zu verwenden.
So habe ich mich aber doch damit durchgequält und erst danach andere Videomodi ausprobiert.
Grins: ging mir genauso. War aber eine gute Übung - insbesondere "modeX" war danach die pure Erholung. Leider habe ich die linearen Bildschirmmodi incl. Mode $13 erst zu allerletzt kennen gelernt. Seitdem habe ich auch überhaupt keine Lust mehr mich mit den BitPlanes rumzuquälen. Nichts ist halt logischer (und schneller) als ein linearer Bildschirm.

Leider gibt es keinen packed4 - 16color - Mode im PC-Bereich, also einen Grafikmode mit 16 Farben, der im Hi/Lo-Nibble 4 bits für die Pixelfarbe verwendet (wie das Farbattribut im Textmode). Das hätte viel vereinfacht, zumindest was BitMaps anbelangt.

Ich hatte auch schon nach Hersteller spezifischen Grafikmodi gesucht, um einfach mal in so einem packed4 Farbmodell zu programmieren. Aber keine meiner Grafikkarten weist so einen Modus aus. Ich hatte dann sogar versucht, per Gewalt einen 640x200/16 planar in einen packed4 - Mode umzuwandeln, indem ich einfach versucht hatte, chain4 einzustellen: Bei den ersten Versuchen hatte der Monitor noch immer gekracht :-), bis ich letztlich dann doch ein stabiles Bild hinbekommen hatte. Aber das Ergebnis war trotzdem strange: irgendwie hing es immer davon ab, welche Farbe der Nachbarpixel hatte, wenn ich meine Pixel setzen wollte. Wie dem auch sei, packed4 ist wohl einfach nicht möglich im PC-Bereich.

Ich habe jetzt eh beschlossen, dass ich eher versuchen werde, Bankswitching mit Mode $13 zu kombinieren. Und da kommt jede Bank-Switching - Methode zur rechten Zeit, zumal ich gerade vor einer ET4000 sitze. Ich bin nämlich gerade am überlegen, ob ich mir eine Bibliothek bauen soll, die für möglichst viele VGAs Mode $13 und Bank-Switching kombinieren kann.

Weißt Du noch, woher man bei der ET4000 weiss, ob im 1280x1024-Mode die Zeilen 160 oder 256 byte groß sind?
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: VGA 16 Color Modi-Programmierung

Beitrag von freecrac »

wobo hat geschrieben:Weißt Du noch, woher man bei der ET4000 weiss, ob im 1280x1024-Mode die Zeilen 160 oder 256 byte groß sind?
Das habe ich leider schon wieder vergessen.
Standard sind dafür vermutlich 160 Bytes je Zeile und 256 byte kann man wohl so einstellen:

Code: Alles auswählen

         mov    dx, 3D4h          ;ET4000:Rasterzeilen fuer Bankgrenzen
         mov    ax, 8013h         ;   Wert/2 im 16 Farbmodus
         out    dx, ax            ;Alt=160 Bytes je Zeile = X/8 Pixel
                                  ;Neu=256 Bytes je Zeile = X/8 Pixel
Dirk
Brueggi

Re: VGA 16 Color Modi-Programmierung

Beitrag von Brueggi »

Danke Euch zwei - da muss ich mal bei Gelegenheit experimentieren :-)
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: VGA 16 Color Modi-Programmierung

Beitrag von DOSferatu »

Doch, es gibt einen Packed4-Mode!
Ich hab den mal irgendwann entdeckt. Also einen 16-Farb-Modus, wo jedes Byte 2 Pixel enthält, jeweils im Low- und High-Nybble.

Zur Grafikprogrammierung auf VGA und VESA hab ich vor einiger Zeit einen Tutorialtext verfaßt, der auf meiner Seite zu finden ist. Da: http://www.imperial-games.de/html/dosd2.htm und dort "Wie funktioniert Grafik?" auswählen.

Wenn ich dran denke, stell ich demnächst mal Code für diesen "Packed" 16-Farb-Mode hier ein.
Brueggi

Re: VGA 16 Color Modi-Programmierung

Beitrag von Brueggi »

Frage: Läuft dieser Packed-Mode in 640x480 auf jeder VGA-Karte? hast du da mal ein paar Code-Fetzen (einschalten des Modus) ? Da ich gerade nach einem guten Ersatz-Modi für 640x480x1 bin, ist der Packed-Mode sehr, sehr nützlich :-)
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: VGA 16 Color Modi-Programmierung

Beitrag von DOSferatu »

Entschuldigung. Ich war eine Weile nicht im DOS-Forum. Ich guck mal nach, wo ich meinen Source dafür habe.
Brueggi

Re: VGA 16 Color Modi-Programmierung

Beitrag von Brueggi »

Keine Hektik :-)
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Re: VGA 16 Color Modi-Programmierung

Beitrag von Dosenware »

Hätte hier
Bomanns
Das Grosse PC-Grafik Buch

steht viel zur Grafikprogrammierung drin, mit recht vielen Listings (Anfang der Woche bekommen, noch nicht groß reingeschaut) - könnte ich dir Ausleihen.
Brueggi

Re: VGA 16 Color Modi-Programmierung

Beitrag von Brueggi »

Danke für die Rückmeldung.

Das Angebot nehme ich gerne an - es würde mir aber auch reichen, wenn du Infos zum 16-Col-PAcked-Mode aus dem Buch "extrahierst" und hier reinstellst. Es geht eigentlich nur um das Einschalten und Ansprechen :-)
Es eilt auch nicht - es ist eh zu heiß um irgendwas zu machen :-)
go32
Kommandozeilenfetischist
Beiträge: 174
Registriert: Sa 24. Okt 2015, 22:51

Re: VGA 16 Color Modi-Programmierung

Beitrag von go32 »

@Brueggi:

Der Strang ist zwar schon paar Jährchen alt. Aber ich möchte gerne die VGA 16 Routinen nach Turbo Pascal portieren. Mit dem integrierten Assembler. Ich mache da nichts anderes, als den Assemblercode in asm end; Blöcke zu packen und dem Block einen passenden Namen zu geben, der die Prozedur beschreibt.

Es gibt da die Varable FLAGS_2, die wohl einen Wert enthält, der anzeigt, ob ich SVGA eingeschaltet habe oder nur Standard VGA.

Aber wo und wie ermittle ich das?

Code: Alles auswählen

cmp    BYTE PTR[FLAG_2], 5 { SVGA ? }
Bei diesem Vergleich wird jedoch vorausgesetzt, dass FLAG_2 korrekt belegt ist.

Und wie komme ich mit Turbo Pascal an das Segment FS ran?

Das dürfte es beim 80286 noch nicht gegeben haben.

Oder wählt ein Turbo Pascal Programm hierfür ein anderes Segmentregister, vielleicht ES?
Antworten