DOS Programmierung Tutorial – VGA Farbpalette
In diesem Artikel erstellen wir eine Farbpalette für die VGA Ausgabe unter DOS. Der Source Code vom letzten Artikel zu VGA wird dabei erweitert um einen Hintergrund mit Farbverläufen zu zeichnen.
DOS Programmierung Tutorial – VGA Farbpalette
Im letzten Artikel haben wir alle Farben Zeile für Zeile ausgegeben und gesehen, dass das Ergebnis kein Farbverlauf ist. Unter DOS gibt es unterschiedliche Farbpaletten in denen Farben abgelegt werden. Man greift auf diese über einen Index zu. Das heißt die Farbe auf Index 10 ist nicht immer die selbe. Man kann selber definieren welcher Farbwert dort zu finden ist. Warum ist das so?
Begrenzter Speicher
Der Videospeicher ist begrenzt, das ist immer so. Heute haben wir jedoch Grafikkarten mit 8 Gigabyte und mehr, können dort locker alle für unser Auge erkennbare Farben abspeichern und zeichnen. Im Rechenbeispiel habe ich gezeigt, dass in den Speicher nicht nur die Farben, sondern auch jedes Pixel des zu zeichnenden Bildes abgespeichert werden müssen. Je höher also die Auflösung, desto weniger Speicher bleibt für Farben übrig.
Farbpalette hinzufügen
Für unser Programm erstellen wir uns eine eigene Farbpalette, wollen wir doch schönere Farbverläufe erzeugen. Ich habe dazu 2 neue Funktionen erstellt die
- eine Farbpalette erstellen
- eine Farbpalette in den Videospeicher legen
dazu benötigen wir einige Konstanten:
1 2 3 | #define NUM_COLORS 256 /* size of color palette */ #define PALETTE_INDEX 0x3C8 /* port number for VGA DAC PEL */ #define PALETTE_DATA 0x3C9 /* port number for VGA DAC data */ |
Die Farbpalette wird beispielsweise so erstellt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | /* creates a color palette for VGA color and returns a pointer to it */ byte* get_color_palette() { byte* pal; int i; pal = (byte*)malloc(NUM_COLORS * 3); /* RGB colors */ /* sky */ for(i=0; i<100; ++i) { /* 6-Bit colors! */ pal[i*3 + 0] = MIN(63, i / 2); /* red */ pal[i*3 + 1] = MIN(63, i / 2); /* green */ pal[i*3 + 2] = 63; /* blue */ } /* ground */ for(i=100; i<200; ++i) { pal[i*3 + 0] = 15; /* red */ pal[i*3 + 1] = ((i-100) / 2) +15; /* green */ pal[i*3 + 2] = 15; /* blue */ } return pal; } |
In dem Code wird lediglich ein Array mit Zahlenwerten befüllt. Das Feld ist Anzahl der Farben * 3 groß. 3 deshalb, weil jede Farbe aus einem roten, grünen und blauen Anteil besteht (RGB Farben). Da unser Code pro Zeile die Farbe eines Index der Palette ausgibt erstellen wir 200 (Auflösung von 320×200) unterschiedliche Farben.
1 2 3 4 5 6 7 8 9 10 11 12 | /* copy color palette array to VGA DAC PEL address */ void set_color_palette(byte* pal) { int i; /* outp writes a byte to hardware port */ outp(PALETTE_INDEX, 0); for(i=0; i<NUM_COLORS * 3; ++i) { outp(PALETTE_DATA, pal[i]); } } |
Kopiert wird das Feld von Farben über eine neue Funktion outp aus dem dos.h Header. Diese Funktion nutzt wieder DOS Funktionalitäten um über das Betriebssystem den Videospeicher zu füllen. DOS bietet dazu jede Menge Hardware Ports an über die man auf Hardware zugreifen kann. In der VGA Sektion findet man dazu:
1 2 | 3C8 VGA video DAC PEL address 3C9 VGA video DAC |
Das Ergebnis sieht wie folgt aus:
Fazit
Wie man sieht muss man sich vor der ersten Zeile Programmcode überlegen was man zeichnen möchte. Danach erstellt man eine Liste aller benötigten Farben und versucht dann diese in den begrenzten Videospeicher in einer Farbpalette abzulegen. Danach kann man das Bild unter Angabe der Indizes der Farben pro Pixel zeichnen. Dieser Prozess macht das Zeichnen von Pixel dann doch wieder etwas komplizierter als gedacht. Wie so oft geht es aufgrund von Hardware Einschränkungen nicht besser.
Eine Antwort
[…] + mehr hier sehen […]