
                             VGA-Kurs - Part #1

An alle, die sich schon ein bichen mit Pascal und Assembler auskennen, und
nun unbedingt Spiele, Demos oder anderes in VGA coden mchten! Hier ist der
erste Teil von "T.C.P.'s Beginner's Guide To VGA Coding"(TM)!
(Anmerkung fr alle erfahrenen Coder: Ihr mt das hier natrlich nicht lesen,
da ihr das sowieso schon alles wit, aber es kann ja nix schaden, gelle? Ach 
so: Falls ich irgendwas falsch mache, knnt ihr mich natrlich berichtigen,
schlielich is ja nobody perfect!)
Wenn meine Annahme stimmt, da viele Leute so was lesen wollen, werde ich
diese Serie fortsetzen, bekomme ich allerdings nicht gengend Resonanz, werde
ich das Schreiben einstellen.
Ich werde in den ersten Teilen die Grundlagen vermitteln und mich spter, bei
gengend Resonanz wie gesagt, auch fortgeschritteneren Teilen der 
VGA-Programmierung annehmen, wie Mode-X, Undokumentierte VGA-Funktionen,
Sprites, HiRes-Coding etc.
Na dann mal ran ans Eingemachte!
Wer Pascal hat, hat vielleicht schon mal ein bichen mit BGIs rumgecodet.
Inzwischen gibt es zwar auch 256-Farben-BGIs aber trotzdem: Verget es! 
Diese Dinger taugen vielleicht fr irgendwelche HiRes-Lame-O-Slow-Anwendungen, 
fr die man das Rad (sprich: SVGA-Routinen) nicht neu erfinden will, aber fr 
Spiele (geschweige denn Demos) - nej, nej, nej, da brauchts schon n' bisserl 
mehr.
"Also, wie komme ich in den 256-Farben-VGA-Modus, ohne an BGIs auch nur einen
Gedanken zu verschwenden?" werdet ihr jetzt fragen. Die Antwort ist absolut
simpel: Inline Assembler! (brigens DAS Demo-Coder-Zauberwort schlechthin!)
Hier also eine Prozedur zum Initialisieren des 256-Farben-Modus:

procedure SetMCGAMode;assembler;
asm
  mov     ax,13h
  int     10h
end;

Wie ja wohl jeder sehen kann, ldt diese Prozedur das AX-Reg mit 13h und ruft
den VGA-Bios-Interrupt 10h auf.
Die VGA-Karte wei nun, da sie in den Modus 13h (320x200 Pixel, 256 Farben)
schalten soll. Was lernen wir daraus? Wir schreiben in AX den Video-Modus,
den wir haben mchten, callen den INT 10h und -baff!- befinden wir uns im
gewnschten Modus. Die Nummer des Standard Textmodus ist brigens 3h. Hier
eine kleine bungsaufgabe fr zu Hause: Wie komme ich zurck in den Textmodus?
Richtig! Wir ersetzen 13h durch 03h.
Den INT 10h sollte man sich brigens gut merken, da er spter sehr wichtig
werden wird.
So, schn und gut, ich bin im richtigen Modus, aber was jetzt? Beginnen wir
mit der simpelsten Operation im Grafikmodus: Das Setzen eines Pixels!
Zuerst einmal: Was hat ein Pixel fr Eigenschaften? 1. X-Koordinate (0-319),
2. Y-Koordinate (0-199), 3. Farbe (0-255).
Moment mal! War da nicht die Rede von 320x200x256 und nicht 319x199x255?
Tja, das ist so: Der Computer fngt nicht bei 1 an zu zhlen wie die meisten
von uns, sondern bei 0. Was also fr uns 1 Dose Coke ist, ist fr den
Prozessor 0 Dose Coke. Was fr uns X-Koord 1 ist, ist fr den Compi X-Koord 0.
Alles klar? Der erste Pixel in der obersten Zeile ist also fr den Rechner
(0,0), der zweite (1,0), der dritte (2,0), usw. Und so wollen wir es hier in
Zukunft auch halten. Wenn man jetzt also solange weiter macht, bis man bei
Pixel (319,0) angekommen ist, geht man in die nchste Zeile und nach links.
Jetzt hat man Pixel (0,1). Das kann man immer weiter treiben, bis man bei
Pixel (319,199) angekommen ist. Jetzt kennt man jeden Pixel persnlich und
kann sie abends zum Essen einladen ;-).
Wie ihr wahrscheinlich schon bemerkt habt, werden Pixel-Koordinaten
folgendermaen angegeben: (X-Wert,Y-Wert).
Damit ihr es euch besser vorstellen knnt, hier noch einmal bildlich:

        X
 0,0> 319,0
             :
             :
Y            :
             :
             :
  V
0,199       319,199

Mit der Farbe verhlt es sich genauso. Versucht dieses um 1 verschobene
System zu verinnerlichen, weil ihr nicht drum herumkommen werdet.
So, puh (Schwei-von-der-Stirn-wisch), das htten wir, aber wie setze ich
jetzt einen Pixel?
Da hilft uns unser alter Freund, der INT 10h.
(Anmerkung fr alle erfahrenen Coder: Keine Panik, wir werden auch noch die
Variante kennenlernen, die ohne das Bios auskommt.)
Hier also eine Prozedur, die einen Pixel an die gewnschte Stelle in der
gewnschten Farbe setzt:

procedure PutPixel(x,y:integer;col:byte);assembler;
asm
  mov     ah,0Ch
  mov     al,col
  mov     cx,x
  mov     dx,y
  int     10h
end;

Will man also einen weien (Farbe 31) Pixel an (55,120) setzen ruft man die
Prozedur mit

PutPixel(55,120,31);

auf. Dieser Befehl schreibt nun ins AH-Reg die Funktionsnummer, in AL die
gewnschte Farbnummer, in CX und DX die X- und Y-Koords. Anschlieend wird
der INT 10h bemht, die Arbeit zu bernehmen. Nun sehen wir im unteren linken
Viertel des Bildschirms einen weien Punkt (vorrausgesetzt, wir befinden uns
im Modus 13h). Nun, dieses Wissen ffnet uns die Tore zu vielen kleinen
Spielereien, die ihr euch jetzt zu Hause ausdenken knnt. Wir knnten zum
Bleistift den gesamten Bildschirm mit Pixeln in beliebigen Farben zuknallen.

program FillScreen;
uses crt;
var n1,n2 : integer;
:
: (Hier stehen die oben
: besprochenen Prozeduren)
:
begin
  randomize;
  SetMCGAMode;
  for n1 := 0 to 319 do
    for n2 := 0 to 199 do PutPixel(n1,n2,random(256));
  readkey;
  SetTextMode;
end.

Schn, nich? Jetzt haben wir einen zugemllerten Screen. Aber wie kriegen wir
ihn wieder leer? Ist schlielich nicht sooo schn auf Dauer!
Die ganz schlauen werden jetzt sagen: "Ist doch ganz einfach! Ich ersetze das
"random(256)" durch "0"!" Tja, auch ne Lsung, aber so einfach wollen wirs uns
nun auch nicht machen. Auerdem wre diese Lsung viel zu langsam, und damit
so unbrauchbar wie ein MS-Produkt ;-). Also, hier die bessere (und schnellere)
Lsung:

procedure ClrVGA(col:byte);
begin
  fillchar(mem[$A000:0],64000,col);
end;

Hier ausnahmsweise mal kein Assembler sondern ein Standard-Pascal-Befehl am
Werk. Er fllt den Speicherbereich ab A000h:0 (64000 Byte, hier blendet die
VGA ihren Bildschirmspeicher ein, 320 x 200 = 64000) mit der Farbnummer in
"Col" auf. Ihr knnt den Screen also in jeder beliebigen Farbe lschen, aber
am gebruchlichsten ist wohl 0 (Schwarz).
Jetzt wo wir schon etwas mehr bewandelt sind, knnen wir uns der Verfeinerung
unseres Wissens widmen. Zum Beilpils: Warum ist unsere PutPixel-Prozedur so
langsam? Ganz einfach: Sie benutzt das Bios! Wenn wir mit dieser Prozedur ein 
Spiel oder sogar ein Demo machen wollten, wrden wir wahrscheinlich nicht 
besonders weit kommen! Will man also wirklich geschwindigkeitsoptimiert coden,
mu man meistens einen anderen, unbequemeren Weg als das VGA-Bios benutzen.
In diesem Fall knnen wir die Prozedur erheblich beschleunigen, wenn wir die
Pixel-Daten direkt in den Bildschirmspeicher schreiben. Erinnert ihr euch?
Der Bildschirmspeicher im Modus 13h ist ein 64000(320x200)Byte groer
Speicherbereich an der Adresse A000h:0. In diesem Bereich stehen die
Farbwerte smtlicher Pixel auf dem VGA-Screen. In den ersten 320 Byte stehen
also die Farbwerte aller Pixel der ersten VGA-Zeile hintereinander. Die
nchsten 320 Byte beinhalten die Werte der nchsten Zeile, usw. bis zum
letzten Pixel, dessen Farbwert an Adresse A000h:63999 steht. Da wir dies nun 
wissen, knnen wir mit Hilfe der Formel

Byte-Adresse = 320 x Y-Koord + X-Koord

berechnen, welche Adresse welcher Pixel einnimmt. Hier also die optimierte
PutPixel-Routine:

procedure PutPixel(x,y:integer;col:byte);
begin
  mem[$A000:320*y+x] := col;
end;

Wer diese Prozedur nun in unser "FillScreen"-Proggi einbaut, wird die
erhebliche Geschwindigkeitssteigerung bemerken. Aber es geht noch schneller!
Und zwar, indem man nie Prozedur in Assembler schreibt (War ja klar! ;-).
Aber das berlasse ich euch fr zu Hause, schlielich sollt ihr auch mal
selber was machen. Gebte Coder knnen bestimmt noch ein paar Clocks
raushauen.
So, das wars dann frs Erste von "T.C.P.'s Beginner's Guide To VGA
Coding"(TM)! Ich hoffe, es hat euch was gebracht, und ich bekomme reichlich
Feedback. Gebt auch eure Wnsche an, was ihr auf jeden Fall in einer der
Ausgaben besprochen sehen wollt. Ich schreibe diesen Kurs gerne, aber nur wenn
sich auch genug Leute dafr interessieren, sonst kann ich mir die Arbeit
sparen! Also, schreibt was!





[ This text copyright (c) 1995-96 Johannes Spohr. All rights reserved. ]
[ Distributed exclusively through PC-Heimwerker, Verlag Thomas Eberle. ]
[                                                                      ]
[ No  part   of  this   document  may  be   reproduced,   transmitted, ]
[ transcribed,  stored in a  retrieval system,  or translated into any ]
[ human or computer language, in any form or by any means; electronic, ]
[ mechanical,  magnetic,  optical,   chemical,  manual  or  otherwise, ]
[ without the expressed written permission of the author.              ]
[                                                                      ]
[ The information  contained in this text  is believed  to be correct. ]
[ The text is subject to change  without notice and does not represent ]
[ a commitment on the part of the author.                              ]
[ The author does not make a  warranty of any kind with regard to this ]
[ material, including,  but not limited to,  the implied warranties of ]
[ merchantability  and fitness  for a particular  purpose.  The author ]
[ shall not be liable for errors contained herein or for incidental or ]
[ consequential damages in connection with the furnishing, performance ]
[ or use of this material.                                             ]
