Wie funktioniert Grafikprogrammierung im Real Mode? (Anmerkung: Dieser Text wurde von mir noch einmal überarbeitet und einige Fehler entfernt. Darunter ein sehr entscheidender Fehler. Die geänderten Bereiche sind mit ##### am Anfang und ***** am Ende markiert. Außerdem Ergänzungen: Mode-Tabelle und Mode-Info-Block werden erklärt.) Zunächst einmal sollte man wissen, was der Real-Mode ist und wie dieser arbeitet, bevor man weiterliest. Dies ist im Text REALMODE.TXT erklärt, den Sie eigentlich an derselben Stelle finden sollten wie diesen Text (GRAFIK.TXT). Grafik wird beim PC in den Speicherbereich $A000:$0000 bis $A000:$FFFF eingeblendet. (Ausnahme: Im Textmode wird der Bereich ab $B000 benutzt (für Monochrom = "Hercules"-Textmode) und ab $B800 für 16-farbigen Textmode. Außerdem wird der Bereich ab $B800 auch für die 4-farbigen CGA-Grafikmodi benutzt Nun, das ist erst einmal uninteressant. Hier soll es um die "richtigen" Grafikmodi gehen. Falls jemanden interessiert, wie die Hercules und CGA-Modi funktionieren, kann ich dies gern noch in einem gesonderten Tutorial erklären. Vielleicht ist es schon jemandem aufgefallen: Das Segment ab $A000 bis $AFFF hat nur 64kByte Speicher. Man kann es auch nicht "erweitern", weil die nachfolgenden Segmente des Speichers für das BIOS, den Upper Memory Block usw. reserviert sind und daher nicht einfach mit Grafik "überschrieben" werden können. (OK, nicht daß man das BIOS wirklich überschreiben könnte...) Das bedeutet, daß man eigentlich nur 64kByte Speicher für Grafik zur Verfügung hat, richtig? Nun - nicht ganz. Der Umstand, daß der Grafikspeicher etwas knapp ausgelegt wurde, wurde den PC-Entwicklern relativ schnell klar. Wenn (wie im Monochrom) ein Pixel nur ein Bit braucht (weil, entweder "an" oder "aus" braucht nunmal nicht mehr), mögen 64kByte ja reichen - ansonsten stößt man bald an eine Grenze. Zugriff auf den Grafikspeicher erlangt man IMMER, indem man ein Segmentregister mit $A000 lädt - und dann darauf zugreift. Wichtig: Anders als beim Speicher (der Gate A20-"Trick") ist es beim Grafikspeicher NICHT möglich, weitere knapp 64kByte anzusprechen, indem man das Segment-Register einfach auf das Segment-Ende (also $AFFF) setzt und dann Bereiche über $000F anspricht!! Diese werden in jedem Fall "Wrap-arounded" - d.h. man landet wieder beim Segment-Anfang von $A000. Grund dafür ist, daß PCs einfach "so gebaut" sind, daß die Speicherzugriffs-Logik auf die Adressen, deren obere 4 Bit = $A sind (also $A0000 bis $AFFFF) so reagiert, daß diese Zugriffe auf die Grafikkarte umgeleitet werden - sowohl Lese- als auch Schreibzugriffe - und daß nur die unteren 16 Bit der sich ergebenden Adresse dann über 16 Adreßleitungen der Grafikkarte übergeben werden. Noch eine wichtige Anmerkung: Grafikkarten-Zugriffe sind (vergleichsweise) langsam - viel langsamer als Zugriffe auf den normalen RAM. Dabei sind Schreibzugriffe schneller als Lesezugriffe. Das liegt daran, daß man Grafikkarten für Schreibzugriffe optimiert hat, da diese viel häufiger gebraucht werden als Lesezugriffe. - Da man wohl davon ausgeht, daß jemand, der eine Grafik in den Speicher legt, ja noch "wissen" wird, was er da hineinlegt. Und daß der Grafikkartenspeicher ja nicht als Zwischenspeicher für irgendwelche Werte gedacht ist, sondern nur als Puffer für die anzuzeigenden Bilddaten (also farbige Pixel). Wie funktionieren Grafikmodi? Die Grafikkarte ist so gebaut, daß sie einfach nur linear den Speicher ausliest und das darstellt, was sie dort beim Lesen findet. Es gibt drei Möglichkeiten, Grafikmodi einzuschalten: 1.) Der Modus ist ein Standardmodus, der vom BIOS unterstützt wird. Dann kann man ihn mit mov AX,Nummer int $10 einschalten. AH ist dabei =0, AL ist =Nummer. Nummer ist dabei ein Grafikmodus. Standard sind hierbei nur die Modi 0 bis 19 (hex. $00 bis $13) Später hinzugekommen sind dann noch $58,$59 und $5A - ein Zugeständnis der Grafikkartenhersteller an die Hersteller von Betriebssystemen und anderen Programmen, die auch mal - wenigstens 16farbige - hochauflösende Grafikmodi brauchten. Für VGA ist hier jedoch nur der Modus $58 (800x600, 16 Farben) interessant, da die anderen mehr Speicher brauchen, als man mit "normalen Mitteln" (also per VGA) ansteuerm kann. 2.) Der Modus ist ein VESA-Modus. Dies setzt voraus, daß die Grafikkarte von sich aus VESA supportet oder daß ein Treiber geladen ist, der VESA bereitstellt. Dann kann man ihn mit mov AX,$4F02 mov BX,Nummer int $10 einschalten. Nummer ist hierbei die Nummer des Modus und sie fängt bei $0100 an und geht per Standard meines Wissens bis $02FF - wenn auch nicht notwendigerweise alle Modi belegt sind. (Wenn man hier Modi unter $100 - also $00 bis $FF - benutzt, werden stattdessen die "normalen" Modi (also die VGA-Modi, die unter 1. beschrieben sind) eingeschaltet. Dies ist ein "Service" von VESA, den man zwar benutzen kann - aber er bringt meines Wissens keine Vorteile. 3.) Man setzt vom Hand die Register der Grafikkarte, um einen entsprechenden Modus zu aktivieren. Hierbei kann man der Phantasie relativ freien Lauf lassen - d.h. man kann sogar eigene Grafikmodi erfinden. Achtung! Alte Monitore nehmen unstandardisierte Modi oder Modi mit einer zu hohen Zeilenfrequenz oft sehr übel und beantworten sie mit einer Selbstzerstörung. Neuere Monitore haben einen diesbezüglichen Schutz eingebaut und schalten sich bei nicht darstellbaren Grafikmodi einfach ab. Am häufigsten wird dies als "Kombination" benutzt. Das heißt, man setzt erst mit der unter 1.) gezeigten Methode einen regulären Grafikmode, damit die meisten der Register schon gesetzt sind und dann ändert man nur noch die Register der Werte, die man gegenüber diesem Modus ändern will. Wie die Modi im Speicher aufgebaut sind: (Ich komme später auf die für den "heutigen" Grafikprogrammierer "interessanteren" Modi zu sprechen - daher die Bemerkungen zu 1-, 2- und 4-Bit Modi überlesen, falls nicht interessiert.) 1-Bit-Modi, auch Monochrom oder "Hercules-Grafik" genannt: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (Hercules ist die Firma, die den damals "erfunden" hat.) Hier wird für einen Pixel nur 1 Bit gebraucht, da es nur 2 Farben gibt. (schwarz oder weiß. Weiß kann natürlich auch grün, bernsteinfarbig oder sonstwas sein, je nachdem, ob man einen "eingefärbten" Monochrom-Monitor hat.) Da nur 1 Bit gebraucht wird, werden 8 Pixel zu einem Byte zusammengefaßt. Hierbei ist das oberste Bit (also 128, bzw $80) der linke Pixel, das unterste der rechte. Eine Zeile mit 640 Pixeln braucht demzufolge 80 Bytes. DIe Aufläsung 640x350 Monochrom (nicht lachen, sowas gibts ehrlich) - braucht also 80x350 = 28000 Bytes. Hercules-Mono-Modi liegen per Standard ab $B000:$0000 im Speicher. Beispiele für diese Modi sind: Nummer (dez) Nummer (hex) Größe Farben 6 $06 640x200 2 (Monochrom) 15 $0F 640x350 2 (Monochrom) * 17 $11 640x480 2 (Monochrom) * = Den Modus 17 gibt es nicht auf der Hercules-Karte. Grund: Er braucht 38400 Bytes, die Hercules hatten jedoch nur 32768 (also 32kByte). Außerdem konnte die Hercules-Karte meines Wissens nur 350- und 400-Zeilen-Modi erzeugen, jedoch keinen 480-Zeilen-Modus. Der 640x200-Modus wird durch einen "Trick" (nämlich "Doublescan") erzeugt, d.h. jede Zeile wird zweimal gelesen, wodurch mit einer 400er Zeilenfrequenz ein 200er Modus erzeugt wird. Auf diesen "Doublescan" komme ich noch zu sprechen. 2-Bit-Modi, auch CGA genannt: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CGA (Color Graphic Array) braucht 2 Bit pro Pixel und kann 4 Farben darstellen. Diese sind standardmäßig schwarz, magenta (also pink), cyan (also türkis) und weiß - können aber auch schwarz, rot, grün und gelb oder schwarz, dunkelrot, dunkelgrün und braun/orange sein. (Einstellbar mit VGA-Registern.) Die 4 Farben werden durch die Bitkominationen 00, 01, 10 und 11 hervorgerufen. CGA gibt es per Standard nur in einer Auflösung, nämlich 320x200 Pixel. Die 2 Bit liegen direkt nebeneinander, ein Byte speichert 4 benachbarte Pixel. D.h. eine Zeile braucht demzufolge 80 Bytes, bei 200 Zeilen werden also 16000 Bytes gebraucht. Standardmäßig stehen 32Kbyte CGA-Speicher zur Verfügung, d.h. man hat Speicher für zwei "Bilder". CGA-Modi liegen per Standard ab $B800 bis $C7FF im Speicher, wobei $B800 bis $BBFF erste "Bild" speichern, $BC00 bis $BFFF das zweite Bild, und so weiter. Leider ist das der Seltsamkeiten noch nicht genug für diese Modi. Um allen eins draufzusetzen, liegen die Zeilen nicht linear angeordnet, sondern jede zweite (also ungerade) Zeile liegt um genau 8192 (also $2000) Bytes versetzt zur vorhergehenden "geraden" Zeile, so daß die Anfangsadressen der erste 8 Zeilen also sind: $B800:$0000 $B800:$2000 $B800:$0050 $B800:$2050 $B800:$00A0 $B800:$20A0 $B800:$00E0 $B800:$20E0 Das ist seltsam - iiegt aber daran, daß damalige Grafikkarten noch "festverdrahtet" waren, d.h. daß eine recht einfach Logik ihr Handeln bestimmte und keine der 3D-fähigen Grafikchips von heute, die leistungsfähiger sind als die CPU, die im PC eingebaut ist - nur damit ein paar Spieleheinis 3D-Ballerorgien veranstalten können... Ich nehme einfach mal an, die merkwürdige Adressierung kommt daher, daß dieser Modus früher mal "interlaced" dargestellt wurde - d.h. bei jedem Bilddurchlauf nur jede zweite Zeile dargestellt, bei nächsten die dazwischenliegenden - weil die Monitore wohl noch ziemlich schwach waren... (obwohl ich mir bei 200 Zeilen kaum noch Interlacing vorstellen kann...) Beispiele für diese Modi sind: Nummer (dez) Nummer (hex) Größe Farben 4 $04 320x200 4 5 $05 320x200 4 Anmerkung: Ich habe niemals herausgefunden, was der genaue Unterschied zwischen den Modi 4 und 5 ist. Es muß einen geben, da ein Bit anders gesetzt wird. (Das Schwarz/weiß-Bit.) Es hat aber keine mir bekannten Auswirkungen bei der Anzeige oder Ansteuern des Modes. Wenn mir einer also dieses Mysterium erklären könnte... Will sagen: Eigentlich gibt es nur EINEN CGA-Modus. Und: Ja, die Farben kann man (siehe oben) ändern - man könnte wahrscheinlich sogar einen 320x400-Zeilen Modus draus machen (mit Doublescan). Nur ist nicht gesagt, daß dieser dann auch so funktioniert wie gedacht. 4-Bit-Modi, EGA ~~~~~~~~~~~~~~~ EGA (Extended Graphics Array) benutzen für eine Farbe 4 Bit, d.h. sie können 16 Farben darstellen. Diese sind zwar eigentlich standardisiert - diese Palette kann jedoch geändert werden. Standardmäßig werden hier die 16 Farben benutzt, die man auch vom Textmode her kennt. Die Ansteuerung der 4-Bit Modi ist die vielleicht zeitraubendste und nervtötendste, die es überhaupt gibt. Schuld daran ist die Tatsache, daß man dazu einfach die 1-Bit-Modi "umgebaut" hat. Der Speicheraufbau ist exakt der gleiche wie bei den 1-Bit-Modi (siehe dort). Natürlich hätte man auf diese Art nur 1 Bit pro Pixel - also nur 2 Farben. Dieses Problem hat man damit gelöst, daß man die Bits nicht "nebeneinander", sondern "übereinander gestapelt" hat. Das bedeutet: Man hat eigentlich 4 Speicher, die alle dieselben Adressen haben und schaltet zwischen diesen 4 Speichern um. Diese nennt man "Planes" (Ebenen). Will man also einen farbigen Pixel setzen, muß man hier in alle 4 Planes nacheinander schalten und das jeweilige Bit setzen oder löschen. Dabei entspricht Plane 0 dem Bit 0 der Farbe, Plane 3 eben Bit 3, für die übrigen gilt das entsprechend. Will man also einen Pixel in Farbe 13 (Hex= $D, binär = 1101) setzen, so muß man Plane 0 einschalten, das Bit setzen, Plane 1 einschalten, das Bit setzen, Plane 2 einschalten, das Bit löschen, Plane 3 einschalten, das Bit setzen. Glücklicherweise kann man (zumindest beim SCHREIBEN) in mehrere Planes gleichzeitig schreiben, so daß man also eigentlich erst nur alle Planes, in denen man das Bit setzen muß, anschaltet, dann das Bit setzt, und dann alle Planes, in denen man das Bit ausschalten muß, anschaltet und das Bit löscht. Ja, ich weiß selbst, wie sich das anhört. Wie ich schon sagte: Damals waren Grafikkarten festverdrahtet. Neue Modi wurden entwickelt, indem man alte Modi einfach nur "aufgebohrt" hat. Es ging nicht darum, schnell zu sein, sondern möglichst einfach nur, überhaupt irgend etwas farbig darstellen zu können. Und wenn alle eine Monochrom-Grafikkarte hatten und man selber hatte 16-farbigen Grafikmode, war man eben der King... Ab EGA war es dann auch, daß als Grafiksegment $A000 benutzt wurde und die vollen 64kByte. Wem es aber aufgefallen ist: Durch die 4 Planes, die man ja nun hatte, hatte man in Wirklichkeit nicht nur 64kByte, sondern das vierfache, nämlich 256kByte (nicht alle hatten 256k, manche auch nur 128kByte (damals, zu Anfang...), damit war dann aber schon der 640x350 Mode mit 16 Farben darstellbar. Wer 256kByte hatte, konnte eben wieder mit zwei Bildschirmseiten glänzen - oder noch höher aufgelöste Modi benutzen, wie z.B. 640x480 mit 16 Farben. Diesen Modus gibts auch heute noch, er ist standardmäßig auf jedem Rechner mit ner EGA (mit 256kByte Speicher) und VGA Karte vorhanden ohne Laden zusätzlicher Treiber. Das ist auch der Grund, wieso Windows im "abgesicherten Modus" diesen Grafikmode benutzt - weil es sich eben darauf verlassen kann, daß er überall funktioniert. Daß er langsam und unbequem anzusteuern ist, ist natürlich der Nachteil. Achja: Wie man die Planes ändert, oder welche Bildschirmseite angezeigt wird (Standard nach Einschalten ist Seite 0, also die erste) oder auch wie man die Farbpalette setzt, kann ich bei Bedarf auch noch erklären. Beispiele für diese Modi sind: Nummer (dez) Nummer (hex) Größe Farben 13 $0D 320x200 16 14 $0E 640x200 16 16 $10 640x350 16 18 $12 640x480 16 88 $58 800x600 16 * 89 $59 1600x1200 16 # 258 $102 800x600 16 VESA! 260 $104 1024x768 16 VESA! 262 $106 1280x1024 16 VESA! * = Nagelt mich nicht drauf fest. Der ist normalerweise nicht standardisiert im VGA. Das kam erst später. # = Dafür reicht reiner VGA-Speicher normalerweise nicht aus. VESA! = Diese Modi sind nur im VESA verfügbar und müssen per VESA- Aufruf eingeschaltet werden! siehe oben 8-Bit-Modi, VGA ~~~~~~~~~~~~~~~ Diese Modi haben 256 Farben, zum Glück nicht in 8 hintereinanderliegende Planes aufgeteilt oder sowas, sondern endlich mal so, daß ein Byte auch einem Pixel entspricht. (Klar, warum soll man die auch quer speichern, wenn sie längs genau in ein Byte passen?) Eine Bildschirmzeile braucht demzufolge genauso viele Bytes, wie es Pixel pro Zeile gibt, 320x200 also genau 320 Bytes pro Zeile. Demzufolge ergibt sich für 320x200 ein Speicherbedarf von 64000 Bytes - und hier kommen wir schon zum Manko des Ganzen: Diese 64kbyte passen grade mal so in die 64kByte "Grafikfenster", das ab $A000 liegt - denn auch hier wird wieder $A000 benutzt. Der Riesenvorteil des Modus 320x200, mit einem Zugriff auch genau einen Pixel darstellen zu können, sowie einfach linear 64000 Pixel 320x200 ansprechen zu können. Die Nachteile sind: 1.) Die Auflösung ist manchen Leuten wohl zu gering und 2.) Es gibt nur eine Bildschirmseite. Zu diesem Modus, der sich fach-intern MCGA nennt, gibt es noch eine Bemerkung zu machen: Eigentlich ist er ein umgepfriemelter CGA-Modus (daher auch der Name). Er benutzt eigentlich die ganzen 256kbyte und liest aber jeden 4. Pixel aus einer anderen Plane. Davon bemerkt der Benutzer nichts, weil der Zugriff auf die Planes "zusammengeschaltet" wurde und sich das ganze Bild nun verhält wie eine 64kByte Plane. Mit Hilfe von Tricks (Mode X genannt) läßt sich dies jedoch umgehen, d.h. es ist dann möglich: 1) diese Planes einzeln anzusprechen, 2) wirklich 256 kByte Speicher zu haben und 3) damit auch natürlich höhere Auflösungen darstellen zu können. Nachteil daran ist, daß immer 4 nebeneinanderliegende Pixel in unterschiedlichen Planes liegen (also die Planes für die Pixel sind so angeordnet: 0 1 2 3 0 1 2 3 0 1 2 3 usw.), statt - wie es für den User vielleicht besser wäre - daß jede Plane genau ein Bild hat. Es ist allerdings schon gut, daß es überhaupt möglich ist, selbst im VGA hohe Auflösungen und mehrere Bilder hinzukriegen. Ich selbst habe schon 800x600, 16 Farben und 512x512, 256 Farben im VGA erzeugt. Es funktioniert, allerdings würde ich das nicht mit nem altersschwachen Monitor empfehlen... Zum Mode-X und anderen VGA-Register-Tricks kann ich mich nochmal gesondert auslassen, das würde jetzt entschieden zu weit führen... Das besondere an diesen Modi ist, daß die Pixel keine "direkte" Farbe haben, sondern nur die Stelle angeben, an der die Farbwerte (rot,grün,blau) für diesen Pixel stehen. Dies ist eine 256 x 3 Bytes große "interne" Tabelle in der Grafikkarte. Diese kann mit einem BIOS-Aufruf per INT gesetzt werden - oder eben "von Hand" durch Schreiben in die VGA-Register. Dabei können die Anteile rot, grün, blau in 64 Stufen (0 bis 63) angegeben werden, jede also 6 Bit - so daß man also 256 Farben aus insgesamt 262144 auswählen kann, die man in einer Palette zusammenfaßt. Wie man Paletten setzt, erkläre ich später - allerdings nur die BIOS- und VESA-Methode, da ich mich hier nicht auf die Beschreibung der VGA-Register einlasse und dies - wenn gewünscht - in einem gesonderten Tutorial tue. Beispiele für diese Modi sind: Nummer (dez) Nummer (hex) Größe Farben 19 $13 320x200 256 !!! 96 $60 1600x1200 256 * 256 $100 640x400 256 VESA! 257 $101 640x480 256 VESA! 259 $103 800x600 256 VESA! 261 $105 1024x768 256 VESA! 263 $107 1280x1024 256 VESA! !!! = Das ist halt der berühmte Mode 13h, der früher sehr beliebt war, weil er so einfach zu handhaben ist. * = Nagelt mich nicht drauf fest. Der ist normalerweise nicht standardisiert - und funktioniert mangels Speicher natürlich nicht in VGA. VESA! = Diese Modi sind nur im VESA verfügbar und müssen per VESA- Aufruf eingeschaltet werden! siehe oben Das besondere an VESA-Modi ist, daß man die Anzahl Bits pro Farbe hier auch statt 6-bit auf jede andere Bit-Breite setzen kann, also z.B. 8-Bit, was dann eine genauso große Palette (256 Farben), aber aus 16777216 statt nur 262144 Farben ermöglicht, da ja jede Farbphase die Werte 0 bis 255 statt nur 0 bis 63 annehmen kann. Damit die Palette weiterhin VGA-kompatibel bleibt, werden Modi beim Aktivieren standardmäßig auf 6 Bit gesetzt. Anmerkungen: - Ich weiß jetzt nicht, ob hier größere Werte als 8 erlaubt sind. - Es gibt VESA-Karten, die dies nicht können. Ob sie 8-Bit-Paletten können, kann in einem Bit abgefragt werden. 15- und 16-Bit-Modi, VESA ~~~~~~~~~~~~~~~~~~~~~~~~~ Diese Modi gibt es nur im VESA, nicht jedoch auf einer reinen VGA-Karte. Um sie anzuschalten ist daher VESA erforderlich. Anmerkung: Natürlich können sie auch auf einer normalen VGA-Karte aktiviert werden - nur ist dies nicht standardisiert und auch die Speicherzugriffe sind hier kein Standard. Im VGA kann man nun einmal maximal 256 kByte Speicher ansprechen - das ist für fast alle hochauflösenden VESA-Modi zu wenig. Diese Modi sind "direkt" Farben Modi, d.h. die Farbwerte werden direkt in den Grafikkartenspeicher gesetzt - es wird keine Farbpalette benutzt. Es werden pro Pixel zwei hintereinanderliegende Bytes benutzt, d.h. eine zeile braucht genau doppelt so viele Bytes, wie sie Pixel hat, im 640x480 also 1280 Bytes pro Zeile, bei 480 Zeilen sind das also 614400 Bytes, bzw 0,6 MB. Im 15 Bit-Mode sind die Bits für die Farbwerte so angeordnet: (Ich empfehle, das ganze in einer Darstellung anzusehen, in der alle Zeichen gleich breit sind, um die (furchtbare) ASCII-"Grafik" hier richtig zu erkennen.) /------- Zweites Byte ---------\ /------- Erstes Byte ----------\ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | x | rot | grün | blau | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ Bits: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Das heißt: Die unteren 5 Bit sind der Blau-Anteil, darüberliegenden 5 sind der Grün-Anteil, und darüber liegen dann der 5 Bits für Rot. Das ganz oberste Bit ist unbenutzt. Das bedeutet, daß man pro Farb-Phase 32 Stufen haben kann (0 bis 31) und damit also insgesamt 32768 mögliche Farben darstellbar sind. Im 16 Bit-Mode sind die Bits für die Farbwerte so angeordnet: /------- Zweites Byte ---------\ /------- Erstes Byte ----------\ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | rot | grün | blau | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ Bits: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Das heißt: Die unteren 5 Bit sind der Blau-Anteil, darüberliegenden 6 sind der Grün-Anteil, und darüber liegen dann wieder 5 Bits für Rot. Das bedeutet, daß man für Rot und Blau 32 Stufen haben kann (0 bis 31) und für Grün 64 Stufen (0 bis 63). Damit ist kein Bit mehr unbenutzt, weil Grün ein Bit mehr hat. Man hat wohl grün gewählt, weil grün die hellste der Farbphasen ist und man daher hier viel mehr Helligkeitsunterschiede optisch wahrnimmt. Damit sind im 16-Bit-Mode insgesamt 65536 Farben darstellbar. WICHTIG: 1) Diese Farbanordnung wird von eigentlich ALLEN mir bekannten Grafikkarten benutzt und hat sich "eingebürgert" - der VESA-Standard sieht dies jedoch NICHT vor! Das einzige, was er vorsieht, ist, daß die Bits einer einzelnen Phase "zusammenhängend" sein müssen. (also man z.B. nicht die Bits für Blau über den gesamten Bereich irgendwie "verteilen" kann) Außerdem sind die Bits einer Phase immer immer in der Reihenfolge, daß die untersten Bits auch immer die untersten Bits der Farbe sind, also ist die Phase 3 IMMER 00011, niemals jedoch 11000 ! 2) Das heißt aber auch: Es entspräche auch noch dann dem VESA-Standard, wenn eine Grafikkarte die Farbphasen in umgekehrter Reihenfolge abspeichern würde, also BLAU "oben" und ROT "unten" - oder ganz anders. Außerdem gibt es wohl auch "variable" Bitbreiten, so daß also hier auch z.B. Bitbreiten von 4 oder 6 Bit bei einer Phase erwartet werden können. 3) Auskunft darüber gibt der Mode-Info-Block, den eine VESA-Karte zu jedem Modus ausgibt. Dieser gibt an, an welcher Stelle das jeweils unterste Rot- Grün- und Blau- Bit liegt und wieviele Bits Rot, Grün und Blau jeweils haben. "Standardmäßig" (d.h. normalerweise) sind diese Stellen bei 15 Bit also: Rot=10, Grün=5, Blau=0 und die Breiten Rot=5, Grün=5, Blau=5 Bei 16 Bit sind diese Werte "standardmäßig": Rot=11, Grün=5, Blau=0 und die Breiten Rot=5, Grün=6, Blau=5 Beispiele für diese Modi sind: Nummer (dez) Nummer (hex) Größe Farben 269 $10D 320x200 32768 (15 bit) VESA! 270 $10E 320x200 65536 (16 bit) VESA! 272 $110 640x480 32768 (15 bit) VESA! 273 $111 640x480 65536 (16 bit) VESA! 275 $113 800x600 32768 (15 bit) VESA! 276 $114 800x600 65536 (16 bit) VESA! 285 $11D 640x350 32768 (15 bit) VESA! 286 $11E 640x400 32768 (15 bit) VESA! 287 $11F 640x350 65536 (16 bit) VESA! 288 $120 640x400 65536 (16 bit) VESA! 302 $12E 320x240 32768 (15 bit) VESA! 303 $12F 320x400 32768 (15 bit) VESA! 304 $130 320x480 32768 (15 bit) VESA! 309 $135 512x384 32768 (15 bit) VESA! 310 $136 320x240 65536 (16 bit) VESA! 311 $137 320x400 65536 (16 bit) VESA! 312 $138 320x480 65536 (16 bit) VESA! 317 $13D 512x384 65536 (16 bit) VESA! 336 $150 400x300 32768 (15 bit) VESA! 337 $151 400x300 65536 (16 bit) VESA! (Liste nicht vollständig, das hab ich nur mal eben von meiner Grafikkarte gezogen - vollständige Liste in "Ralph Brown's Interrupt List" oder bei OBI.) Achja, und hier gehts dann nämlich schon los: Diese Nummern sind NICHT standardisiert. Die Modi über 8 bit (also über 256 Farben) sind nämlich nicht standardisiert an eine Stelle festgelegt - und können daher prinzipiell eigentlich auch irgendwelche anderen Nummern haben. - Da ab VESA 2.0 (das die Modi mit 15,16,24 und 32 Bit einführt) nämlich auch die "Lage" eines Modes freigegeben ist und man daher die "Available Mode Table" (also die Tabelle der verfügbaren Modi) selber "abscannen" muß. Das ist zwar eigentlich schade - aber das müßte man ja ohnehin: Denn man kann nicht "einfach so" davon ausgehen, daß jede Grafikkarte auch alle Modi darstellen kann. Ein Grund dafür ist z.B. der vorhandene Speicher. der Modus 1024x768, 16Bit braucht 2 Byte pro Pixel (16Bit) und insgesamt hat er 1024x768 = 786432 Pixel, also (x2) 1572864 Bytes, oder genau 1,5 MegaByte. Das heißt, daß eine Grafikkarte, die nur 1 MB Grafikkartenspeicher hat (wie z.B. meine) diesen Modus nicht darstellen kann - selbst wenn sie technisch sowohl zu 16-Bit-Farben, als auch zu Auflösungen von 1024x768 fähig ist. (und 1024x768 mit 256 Farben, also 8 Bit, auch darstellt). Merke: Ein Modus wird nur dann unterstützt, wenn mit dem vorhandenen Speicher der Grafikkarte mindestens eine Bildschirmseite vollständig angezeigt werden kann. Anmerkung: Die Grafikkartenhersteller sind bemüht, die Modi an die für sie "gebräuchliche" Stelle zu setzen, d.h. daß ein Modus an der Stelle landet, wo er von allen anderen auch benutzt wird. Aber, wer HTML kennt, weiß, wozu "offene" Standards führen... 24- und 32-Bit-Modi, VESA ~~~~~~~~~~~~~~~~~~~~~~~~~ Im Prinzip gilt hier alles, was schon zu 15 und 16 Bit gesagt wurde. Nur, daß diese Modi 3 oder sogar 4 Bytes pro Pixel brauchen. Das ist auch der einzige Unterschied zwischen 24- und 32-Bit-Modi. Denn normalerweise bleibt bei 32-Bit-Modi das vierte Byte unbenutzt, kann also beliebige Werte annehmen, ohne daß dies Einfluß auf die Darstellung hat. (Das ist nicht ganz richtig. Das Byte wird in der offiziellen Dokumentation als "reserviert" bezeichnet. Es gibt ein Bit in der VESA-Abfrage, das angibt, ob die Benutzung dieses 4. Bytes möglich ist oder nicht.) Standardmäßig liegen die Bytes für die 3 Phasen eines Pixels also so im Speicher: Bei 24 Bit: Blau, Grün, Rot. bei 32 Bit: Blau, Grün, Rot, Reserviert Hier sind auch - genau wie bei 15/16-Bit Modi - andere Anordnungen möglich, beispielsweise Rot, Grün, Blau oder ähnliches. Normalerweise wird dies nicht gemacht - aber, verlaß Dich mal auf Standards... Beispiele für diese Modi sind: Nummer (dez) Nummer (hex) Größe Farben 271 $10F 320x200 16777216 (24 bit) VESA! 274 $112 640x480 16777216 (24 bit) VESA! 289 $121 640x350 16777216 (24 bit) VESA! 290 $122 640x400 16777216 (24 bit) VESA! 318 $13E 320x240 16777216 (24 bit) VESA! 319 $13F 320x400 16777216 (24 bit) VESA! 320 $140 320x480 16777216 (24 bit) VESA! 325 $145 512x384 16777216 (24 bit) VESA! 338 $152 400x300 16777216 (24 bit) VESA! (Liste wieder nicht vollständig) Wichtig ist bei VESA-Modi - aber ganz besonders beim 24-Bit-Modus! - daß man die Länge der Scanline auf jeden Fall aus dem Mode-Info-Block holen sollte, statt einfach davon auszugehen, daß sie bei 16 Bit z.B. doppelt so lang und bei 24 Bit dreimal so lang wie die Breite des Bildes in Pixeln ist. Denn: 1) Man kann nur innerhalb eines 64k "Fensters" die Grafikdaten ansprechen. 2) Wären die Scanlines exakt so lang, wie eine Pixelzeile x3, dann wäre am Ende eines 64k-Fensters die Grenze "mitten im Pixel", d.h. man müßte, um diesen Pixel zu setzen, das Fenster, also die "Bank" ändern. Dies wird jedoch vermieden - indem die Scanline einfach so breit gemacht wird, daß am Ende z.B. 1 oder 2 Bytes "verschwendet" werden - aber dafür die Pixel eben immer an glatten 64kByte-Grenzen aufhören. 3) Zu diesen Banken komme ich später noch - sie sind wichtig, um im Real Mode (16-Bit-Address-Mode des PC) überhaupt VESA benutzen zu können. Frage: Wozu gibts eigentlich die 32-Bit-Modi, sie verschwenden doch offensichtlich nur ein Byte pro Pixel und brauchen deswegen ein Drittel mehr an Speicher? Antwort: Weil sich 4 Byte vom Computer aus wesentlich leichter ansprechen lassen als 3-Byte. Es gibt nunmal keine 24-Bit-Register im PC - man kann Register 8-Bit, 16-Bit oder 32-Bit benutzen. Auf die Art kann man einen 32-Bit-Pixel mit einem einzigen Zugriff setzen. Desweiteren läßt sich die Pixelposition so schneller in Assembler berechnen. Eine "Multiplikation" mit 4 (für 32bit, also 4 Byte) wird gemacht, indem man einfach die Adresse um 2 Bit nach links verschiebt. Frage: Wieso gibts dann auch 24-Bit-Modi auf manchen Grafikkarten? Antwort: Weil diese weniger Speicher brauchen und man damit selbst auf einer Grafikkarte, die nicht soviel Speicher hat, 16777216-farbige Modi haben kann. Für 2-Bit-Modi: Wie man die Palette setzt ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Eigentlich gibts hier nur 2 "Standard" Paletten, die man wie folgt setzen kann: mov AH,$0B mov BX,$0100 oder $0101 int $10 Wenn BL=0 ist, wird die "Standard" Palette (schwarz, cyan, magenta, weiß), wenn BL=1 ist, wird die alternative Palette (schwarz, grün, rot, gelb) benutzt. Dies ist eigentlich nur in CGA-Modi gültig. Für 4-Bit-Modi: Wie man die Palette setzt ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Hier kann man auch die "Palette" setzen - allerdings eher so, daß man die Farben vertauschen kann. mov AX,$1000 mov BL,Nummer_der_Farbe (0 bis 15, oder 17) mov BH,neuer_Farbwert int $10 Nummer_der_Farbe ist eine der 16 Farben, die man benutzen kann. 17 ist (nur in Textmodi) die Farbe des "Overscan"-Bildschirmrahmens. Es gibt noch andere Werte, die andere GRafikkarten-Register beeinflussen - dies ist jetzt jedoch nicht wichtig. Ich glaube, neuer_Farbwert ist hier nicht wirklich eine von 16 Farben, sondern eher ein Wert von 0 bis 63, pro Farbphase 2 Bit (also insgesamt 6) und etwas "krude" verteilt (kann das gerne erläutern!). D.h. man hat hier die Wahl aus insgesamt 64 Farben... Es gibt noch einen zweiten Befehl, der nicht nur eine einzelne Farbe, sondern die gesamte Palette setzt: mov AX,$1002 LES DX, Pointer auf Palette (also die Palette muß an ES:[DX] liegen. mov BH,$00 ;normalerweise nicht nötig, manche BIOSe sollen aber ;abstürzen, wenn man's nicht macht. int $10 Das heißt, daß man an die Stelle von ES:[DX] bis ES:[DX+16] genau 17 Werte für die Farben legen muß, die ersten 16 für die 16 benutzten Farben, der 17. für die "Rahmen"-Farbe. Falls jemanden interessiert, wie die Farbwerte in dieser Palette angeordnet sind, die 6 Bits der Farben sehen so aus: +---+---+---+---+---+---+---+---+ | | | R1| G1| B1| R2| G2| B2| +---+---+---+---+---+---+---+---+ Bits 7 6 5 4 3 2 1 0 Dabei ist Rot aus R1 und R2 zusammengesetzt, Grün aus G1 und G2 zusammengesetzt Blau aus B1 und B2 zusammengesetzt. Jede Phase kann also 4 Werte annehmen. Und - richtig gesehen: Die "unteren" Bits stehen "über" den oberen Bits! oder anders ausgedrückt: Rot ist R2*2+R1 usw. Umrechnung in 256 Farben wäre, daß man den Wert *85 nimmt. (Umrechnung in 64 Farben eben *21). Dies ist aber nur wichtig, wenn man wirklich a) 4-Bit Modi (16-farbig) benutzen will und b) die "Palette" ändern will. Für 4-Bit und 8-Bit-Modi: Wie man die Palette setzt ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Es gibt drei Möglichkeiten, eine Palette zu setzen: 1) Mit Hilfe der BIOS-Funktion, 2) mit Hilfe der VESA-Funktion, 3) von Hand durch Zugriff auf die VGA-Register. Wenn man hier eine Palette für einen 4-Bit-Modus setzt, kann man aus allen 262144 VGA-Farben wählen. Zu beachten ist hierbei, daß dies natürlich erst ab VGA möglich ist - also normalerweise nicht im EGA funktioniert. 1) BIOS-Funktion zum Setzen der Farbpalette Erste Möglichkeit, Farbe einzeln setzen: mov AX,$1010 mov BX,Farb_Nummer ; (Nur 0 bis 255, also $00 bis $FF sind gültig ; BH ist also immer =$00) mov DH,Rot-Wert ; (0 bis 63) mov CH,Grün-Wert ; (0 bis 63) natürlich kann man die Werte für grün... mov CL,Blau-Wert ; (0 bis 63) ... und blau auch gleich in CX laden. int $10 Zweite Möglichkeit, mehrere Farben gleichzeitig setzen: mov AX,$1012 mov BX,Farb_Nummer der ersten Farbe ($00 bis $FF) mov CX,Anzahl zu setzender Farben (1 bis 256, also $01 bis $100); LES DX,Pointer_auf_Palette int $10 ;d.h. hier muß in ES:[DX] wieder eine Palette im Speicher liegen, an der ;bis zu 768 (256x3) Werte liegen für die Farben, die zu setzen sind. ;Die Werte betragen wieder 0 bis 63. Anmerkung: Es ist egal, ob die Werte größer werden als 63, es werden jedoch nur die unteren 6 Bit benutzt, die oberen beiden werden im VGA ignoriert. Es ist möglich, hiermit auch die Paletten für 16-Farb-Modi zu setzen. Die 16 Farben sind in Grafikmodi soweit ich weiß Farbe 0 bis 15. In Textmodi (wo dies auch funktioniert), entsprechen die 16 Farben (per Standard) 16 Farben aus einer "gedachten" 64-Farben-Palette. Dabei haben die 16 Farben folgende Paletten-Nummern: (Falls einer nicht weiß, was magenta ist: Das ist so'ne Art pink.) Farbe Bezeichnung Paletten-Nummer 0 schwarz 0 1 blau 1 2 grün 2 3 cyan 3 4 rot 4 5 magenta 5 6 orange/braun 20 7 hellgrau 7 8 dunkelgrau 56 9 hellblau 57 10 hellgrün 58 11 hellcyan 59 12 hellrot 60 13 hellmagenta 61 14 gelb 62 15 weiß 63 D.h. um die 16 Textmode-Farben zu ändern, muß man die Farben 0,1,2,3,4,5,20,7,56,57,58,59,60,61,62,63 der Palette ändern. Dieser Trick funktioniert allerdings nur in VGA! In EGA oder CGA sollte man dies also nicht versuchen. (Anmerkung: Es macht natürlich nichts, wenn man die anderen "Farben" mit setzt...) 2) VESA-Funktion zum Setzen der Farbpalette mov AX,$4F09 mov BL,$00 ;Auch $80 möglich, siehe unten mov CX,Anzahl Farben ;maximal 256, also alle. mov DX,Erste Farbe ;Wenn alle, dann 0 (also die erste) LES DI,Pointer_auf_Palette int $10 in ES:[DI] (im Speicher) steht nun eine Palette für die zu setzenden Farben. (und zwar, weil man sie vorher dahingelegt hat). DX ist die erste Farbe, die man setzen will ($00 bis $FF), CX gibt wieder an, wieviele Farben man setzen will. Zu beachten ist hierbei, daß die Farbwerte wieder ein 4. Byte haben, d.h. Rot, Grün, Blau und "Reserviert". Sie liegen so alle direkt hintereinander. Im "Standard" Modus haben diese Farben - genau wie bei VGA - Werte von 0 bis 63 (also 6-Bit). Dazu gibt es aber Abhilfe. Anmerkung: Wenn man BL=$80 benutzt, wird die Palette während des "Vertical Retrace" gesetzt - damit das kurze setzen kein "Flimmern" erzeugt. Dies wird nicht von allen Grafikkarten unterstützt - kann man abfragen. Bei denen die es nicht unterstützen, bin ich nicht sicher, ob sie den Wert $80 einfach ignorieren, oder ob sie ihn als $00 annehmen. Man sollte hier beachten, daß dann natürlich auf den nächsten Retrace GEWARTET wird!! Der Retrace ist der kurze Moment, wenn der Monitor mit dem Bildaufbau am Ende ist und der Elektronenstrahler wieder "zurückfährt" zum Bildanfang. - In diesem Moment werden keine Pixel gesetzt - also störts auch nicht, wenn man da die Palette setzt. Dieser Moment ist auch der beste, wenn man zwischen zwei "Bildschirmseiten" umschalten will, damit dies eine flüssige "Animation" erzeugt und kein häßliches Flackern. Die Abhilfe für die 6-Bit-Farben mov AX,$4F08 mov BX,$0800 int $10 Damit setzt man die "Farbbreite" pro Phase auf 8 bit. D.h. die Werte in der Farbpalette können nun 0 bis 255 betragen. Dabei ist BL immer =0 (für die "Funktionsnummer") und BH gibt an, wieviele Bits pro Farbphase (also für Rot, Grün, Blau) man benutzen will. Es ist hier natürlich auch möglich, sowas wie 1 zu nehmen, dann hat man eben nur 8 mögliche Farben... Der Standardwert ist hier übrigens 6. Der ist zu Anfang so gesetzt, um kompatibel zu VGA zu sein. Ob 8-Bit-Modes möglich sind, kann in einem Bit bei VESA abgefragt werden. 3) Setzen der Palette über VGA-Register Dies wird im allgemeinen nur empfohlen, wenn man der totale Freak ist und überhaupt keine der Standard-Funktionen nutzen will... Wenn man Pech hat, ist die Grafikkarte nicht VGA-Registerkompatibel... Ich erkläre dies hier nicht - das Ansprechen der VGA-Register über Ports usw. ist eigentlich nochmal ein eigenes Tutorial wert... Sollte also Interesse an sowas bestehen, Mail an mich. Wie gesagt: Mit VGA-Registern kann man noch ne Menhe anderer Spielereien machen. Habe z.B. mal so abstrakte Grafikmodi wie 384x256 erzeugt... Die "anderen" 4-Bit-Modi ~~~~~~~~~~~~~~~~~~~~~~~~ Es gibt noch eine andere Möglichkeit, 4-Bit-Modi zu haben. Denn dieser Kram mit den Einzel-Farb-Bits in 4 Planes ist ja nicht gerade die wahre Lehre. Besser wäre hier ja ein Modus, in dem man die 4 Bits so verteilt, daß sich zwei nebeneinanderliegende Pixel immer ein Byte teilen, so daß der eine die oberen, der andere die unteren 4 Bits benutzt. Und so einen Modus gibt es auch! - das ist nur ein Bit in einem VGA-Register. (Auf manchen Grafikkarten muß man dann allerdings kurz die Palette anpassen, damit das funktioniert.) Und: Ja, ich habe mich ne ganze Zeitlang mit dem Quälen der VGA-Register beschäftigt und dabei auch noch viele andere interessante Sachen herausgefunden - beispielsweise über einen Textmodus, in der ein Zeichen nicht nur 2 (Vorder-/Hintergrund) sondern 4 Farben (aus 256 möglichen!) haben kann, sowie auch einen Textmodus mit 512 Zeichen. Desweiteren gibt es insgesamt 8 mögliche Zeichensätze, zwischen denen man umschalten kann, und Zeichen können 1 bis 32 Zeilen haben... Wie gesagt: Mit VGA-Registern läßt sich eine Menge anstellen, weil das ja "direkte" Programmierung ist. Bei VESA ist man darauf angewiesen, was der Hersteller einem geben will. Andererseits ist der Vorteil von VESA natürlich, daß es standardisiert ist. Spezielle VGA-Spielereien, wie grade eben beschrieben, funktionieren z.B. nicht unbedingt auf jedem Laptop oder so, weil diese Laptop "Grafikkarten" VGA nur emulieren... Diese ominösen "Planes" ~~~~~~~~~~~~~~~~~~~~~~~ "Planes" gibts nur im VGA. Sie dienen dem Setzen der einzelnen Bits beim 4-Farb-Modus, sowie der Wahl der Plane im sogenannten Mode-X. Wer VESA programmieren will, braucht dies NICHT. Eine Plane wird so gesetzt: mov DX,$03C4 ; Port $03C4 = wählt VGA-Register aus mov AL,$02 ; VGA-Register 2 (für "Nummer der Plane") out DX,AL inc DX ; erhöhen (also auf 03C5) mov AL,$01 ; normal = 1,2,4 oder 8 out DX,AL Dies bedeutet, daß man auch mehrere Planes gleichzeitig setzenkann, mit dem Ergebnis, daß dann das geschriebene Byte an allen Planes landet, die man auf 1 gesetzt hat. Standardmäßig sind alle Planes aktiviert, also 0F (=15). (Das heißt, die aktiven Planes sind BIT-codiert!) Anmerkung: Die Befehle mov DX,$03C4 mov AX,$0201 out DX,AX um das ganze "zusammenzufassen", funktionieren imo nicht. Denn dann werden die Werte 01 und 02 meines Wissens beide nacheinander an $03C4 gesendet. Dies setzt die Plane nur zum SCHREIBEN! Zum LESEN muß man ein anderes Register benutzen, nämlich: mov DX,$03CE ; Port $03CE = wählt VGA-Register aus mov AL,$04 ; VGA-Register 4 (für "nummer der Plane") out DX,AL inc DX ; erhöhen (also auf 03CF) mov AL,$00 ; normal = 0,1,2, oder 3 out DX,AL Beim LESEN kann man nicht mehrere Planes gleichzeitig setzen, sondern immer nur eine - das ist auch klar, denn was soll man schließlich beim Auslesen für einen Wert erhalten, wenn z.B. zwei Planes aktiv wären und in beiden an "derselben" Stelle ein unterschiedlicher Wert steht? Die "Banken" ~~~~~~~~~~~~ Die Banken ergeben sich aus zwei Dingen: 1.) Das "Grafiksegment" (ab $A000) hat nur 64kByte. 2.) Grafikmodi im VESA brauchen viel mehr Speicher als 64kByte. Also mußte irgendeine Möglichkeit gefunden werden, diesen Speicher anzusprechen und dabei trotzdem mit dem normalen Grafiksegment auszukommen. Gehen wir mal davon aus, daß wir eine gute VESA-Grafikkarte haben, mit einer "Granularität" von 64kByte. Diese kann theoretisch auch geringer sein - ist dies aber normalerweise nicht... Die Granulatität kann man wieder im Mode-Info-Block abfragen. (siehe wieder Ralph Browns Interrupt Liste, Funktion $4F01 bei Int $10.) Die Wahl der Bank passiert so: Beim VESA wird von "linearem Speicher" ausgegangen, das heißt, daß der Speicher bei 0 anfängt und bis zum Ende des Grafikkartenspeichers geht. Das bedeutet, daß Bank 0 von $00000 bis $0FFFF geht, Bank 1 von $10000 bis $1FFFF, Bank 2 von $20000 bis $2FFFF - und so weiter. Das heißt, um eine Pixelposition im VESA-Speicher zu berechnen, muß man folgendes tun (X = Spalte, Y = Zeile des Punktes) : Adresse = Y * ScanLine + X * Breite Breite ist dabei die Anzahl Bytes, die ein Pixel braucht. Im 8-Bit Modus ist dies =1, d.h. da kann man auch schreiben: Adresse = Y * ScanLine + X "ScanLine" ist die Breite einer Zeile im Grafikspeicher. Zu erfragen - klar, wieder im Mode-Info-Block (Funktion $4F01). Diese ist normalerweise zwar genauso breit wie es Pixel pro Zeile gibt * Bytes pro Pixel - kann aber auch (z.B. bei 24-Bit-Modi) abweichen. Desweiteren gibt es auch eine Möglichkeit, (ab VESA 2.0) diese Scanline-Breite selbst festzulegen - sofern die Grafikkarte dies supportet. Damit kann man die ScanLine z.B. auf eine 2er Potenz legen. Will sagen: Legt man sie im 800x600-Modus auf 1024 statt 800, so braucht der Modus zwar dann 614400 Bytes (weil "rechts" eben 224 Bytes nicht benutzt werden) allerdings kann man Y * Scanline einfach berechnen, indem man Y um 10 nach links verschiebt. ICH für meinen Teil benutze eine andere Methode: Ich lege eine Tabelle an, in der für jeden Y-Wert seine Startadresse drinsteht (also Y*ScanLine). Auf diese Art spare ich die Multiplikation. Weil Multiplikationen eben mehr Rechenzeit kosten... Hat man diese Adresse berechnet, so merkt man relativ schnell, daß diese auch größer als 65535 werden kann. Und genau das ist der Knackpunkt: Alles, was da vorn "übersteht", kann man ja nicht direkt ansprechen, weil das Segment ab $A000 nur 64kByte groß ist. Dieses "Überstehende" (also die oberen 16 Bit) ist die "Bank" die man setzen muß. Dies geschieht mit Funktion $4F05: mov AX,$4F05 mov BX,$0000 ; dies kann man mit xor BX,BX schneller machen! mov DX,Bank-Nummer D.h. die oberen 16 Bit der Pixel-Adresse lädt man nach DX. Die unteren 16 Bit der Pixel-Adresse lädt man z.B. nach DI, nach ES lädt man $A000 und schon kann man mit Zugriff auf ES:[DI] den Punkt an diese Stelle setzen. Wichtige Anmerkung: Diese "Bank-Umschaltung" ist der Pferdefuß der ganzen Angelegenheit. Sie kostet ein wenig Zeit und sie ist auch ein wenig "umständlich" - aber unter den gegebenen Umständen kann man froh sein, daß die VESA überhaupt eine so relativ einfach zu benutzende Möglichkeit gefunden hat, bis zu 4 GB Grafikkartenspeicher direkt anzusprechen! Man sollte dieses jedoch nicht überstrapazieren - und nicht bei jedem Pixel die Bank umschalten. Eine Möglichkeit ist zB, wenn man eine Bank umschaltet, sich diese zu merken. Und immer, wenn man erneut eine Adresse berechnet für einen zu setzenden Pixel oder andere Grafikelemente - zu prüfen, ob die Bank geändert werden muß (also ob die oberen 16 Bit der Adresse nicht mehr dieselben sind wie beim letzten Zugriff) - und NUR DANN eine Bankumschaltung mit Funktion $4F05 vorzunehmen. Anmerkung: Es gibt eine Möglichkeit, statt des INT $10 diese Bankumschaltung wie eine "Unterprogramm" aufzurufen. Dazu kann man wieder die VESA-Informationen (sie ahnen es: Mode-Info-Block) abfragt. Besteht die Möglichkeit des direkten Aufrufs, so steht die Adresse dort eingetragen - ansonsten steht dort einfach $0000:$0000. Wer etwas raffinierter ist, kann auch einfach die Assembler-Routine, die an der angegebenen Adresse steht, auslesen und in sein Programm kopieren. Dies erfordert jedoch natürlich, daß man die Befehle interpretiert usw... Daher ist dem Neuling von solchen Spielereien abzuraten. Es hört sich jetzt viel einfacher an, als es in Wirklichkeit ist. Anmerkung zu Banken: Wenn man Pech hat, hat die Grafikkarte nur eine Bank-Größe von 4kbyte statt 64kByte - die kleinstmögliche Größe ist hier 1 kByte (da die Größen in kByte angegeben werden. Die größtmögliche Größe wäre zwar 65535 kByte - was aber natürlich Schwachsinn wäre, weil man ja ohnehin keine Banken größer als 64kbyte gebrauchen könnte. Daher ist dieser Eintrag maximal 64. Ist die Bank-Größe (also die sogenannte "Granularität") zB nur 4 kbyte groß, so können nur die unteren 12 bit direkt angesprochen werden und die oberen 20 bit sind zu setzen - bzw natürlich nur 16 bit - da es maximal 65536 mögliche solcher "Banken" geben kann. Die Adresse würde sich also wie folgt ermitteln (Beispiel für 32 bit): Angenommen, die Adresse steht in EDX: mov DI,DX ; nach DI retten and DI,$0FFF ; nur die unteren 12 Bit benutzen shr EDX,12 ; und die Bank-Nummer ermitteln Den Befehl and DI,$0FFF kann man natürlich weglassen - da in der Regel bei kleineren Bank-Größen die oberen Bits ohnehin "ausgeblendet" werden - so daß also hier automatisch nur die unteren benutzt werden (Grund: die oberen Adreßleitungen sind dann einfach nicht vorhanden. Wären sie es, wäre ja auch der entsprechende Speicher da. Und dann bräuchte man die Bank nicht auf 4kB begrenzen, sondern könnte gleich die vollen 64kB benutzen. Danach steht in DI z.B. der Offset in den Grafikkartenspeicher und in DX wie gewünscht die Nummer der "Bank". Anmerkung: 1) Bank-Größen <>64kByte sind heutzutage, (im Zeitalter der Grafikkarten mit 1 GB Speicher und so) eigentlich nicht mehr üblich. Wenn ich so'n Mist überhaupt supporten würde, dann in einer getrennten Pixel-Routine, die nur dann benutzt werden würde, wenn die Bank-Größe wirklich <>64 wäre. Damit spart man nämlich ne Menge Rechenleistung. Merke: Keine Grafikroutine kann schnell sein, wenn schon die Pixelroutine langsam ist! 2) Mir ist nicht bekannt, daß es jemals Bankgrößen gegeben hätte, die man nicht hätte "bitweise teilen" können (also mit AND und SHIFT, wie oben beschrieben). Mit anderen Worten: Bank-größen sollten eigentlich nur sein: 1,2,4,8,16,32,64 kByte. (also 1024,2048,4096,8192,16384,32768,65536 Bytes) Zu diesen Bank-Umschaltungen noch zwei Anmerkungen: ############################################################################## 1) Ich hatte im ursprünglichen GRAFIK.TXT behauptet, daß die ATI Radeon-Serie, sowie eventuell einige andere Grafikkarten bei der Bankumschaltung einen Bug produzieren, so daß die Umschaltung nur für Schreibzugriffe funktioniert, aber bei Lesezugriffen die Bank auf Bank 0 bliebe. DAS IST FALSCH. In Wirklichkeit muß man dazu im Mode-Info-Block (siehe dort!) die Bytes 2 und 3 auslesen. Es ist nämlich möglich, daß es statt der EINEN auch ZWEI Banken gibt. Diese können entweder NUR-SCHREIBEN, NUR-LESEN oder BEIDES sein. Das Byte 2 gilt dabei für Bank 0 und das Byte 3 für Bank 1. Die unteren 3 Bits dieser Bytes geben dabei an, wie diese Bank "funktioniert": Bit 0 = Die Bank existiert. Bit 1 = Die Bank ist lesbar. Bit 2 = Die Bank ist schreibbar. (Anmerkung: Wenn Bit 0 nicht gesetzt ist, ist die Bank nicht vorhanden.) Wenn also die unteren 3 Bits =7 ergeben, so gilt das normal oben Gesagte, d.h. mit dem INT $10, AX=$4F05 und BX=BANK-NR (meist also 0) schaltet man die Bank für LESEN UND SCHREIBEN um. Sind die unteren 3 Bits =5, so kann man in diese Bank NUR SCHREIBEN. Sind die unteren 3 Bits =3, so kann man von dieser Bank NUR LESEN. Es kann außerdem sein, daß die Banken unterschiedliche Adressen haben. Also, daß Bank 0 das Segment $A000 und Bank 1 das Segment $B000 hat. Diese Segmente sind in den Words des Mode-Info-Blocks 8/9 und 10/11 auszulesen. SOLLTE wirklich der Fall eintreten, daß zum Schreiben und Lesen unterschiedliche Bänke benutzt werden, so empfehle ich, dafür gesonderte Routinen zu verwenden, anstatt dies jedesmal abzufragen. ****************************************************************************** 2) Diese Bankumschaltungen sind nicht nötig, wenn die Grafikkarte den sogenannten LFB-Mode ("Linear FrameBuffer") beherrscht. In diesem Fall braucht man nur das Bit 14 des grafikmodes zu setzen, also statt z.B. mov BX,$0112 würde man schreiben: mov BX,$4112 Dies setzt natürlich voraus, daß die Grafikkarte dies anbietet. Dieser Modus blendet den gesamten Grafikkartenspeicher an eine Stelle im oberen Speicher des PCs ein - so daß man ihn dort lesen/schreiben kann. Er KOPIERT NICHTS DAHIN! Meistens werden dafür sogar Adressen benutzt, die es normalerweise gar nicht gibt. Dies dient nur dazu, es wie "normalen Speicher" linear ansprechen zu können. Leider hat dieser Modus den Nachteil, daß man im Real-Mode natürlich ohnehin nur indirekten Zugriff auf den oberen Speicher hat - was dies eigentlich noch langsamer macht als das oben beschriebene "Banked" Modell. Und desweiteren kann man im Real Mode ohnehin nur immer gleichzeitig auf 64kByte innerhalb eines Segments zugreifen, so daß man also in jedem Fall bei Adressen mit Reichweiten über 64kByte die Segmente wechseln müßte. ############################################################################## Die Mode/Fähigkeiten-Tabelle (Anmerkung: Diese Informationen sind aus der "Ralph Brown's Interrupt List" entnommen und von mir übersetzt worden (mit Erklärungen).) Um die Tabelle mit den Fähigkeiten der VESA-Version auf der Grafikkarten UND eine Liste der vorhandenen (unterstützten) VESA-Modes zu erhalten, ist dieser Aufruf zu verwenden: mov AX,$4F00 LES DI,Buffer (512 Bytes Buffer sind zu reservieren) int $10 Man sollte in die ersten 4 Bytes des Buffers die Bytes 86,66,69,50 (hex $56,$42,$45,$32) hineinschreiben, für "VBE2". Das bewirkt, daß die Informationen für VESA 2.0 gegeben werden. Steht dort vorher etwas anderes, wird (abwärtskompatibel) die Information für VESA 1.0 / 1.2 gegeben. Nach dem Aufruf (wenn erfolgreich, also VESA vorhanden) steht in AL=$4F und in AH=$00. Steht dort $01, so trat ein Fehler auf. Ab VESA 2.0 gibt es auch: AH=$02 (Funktion mit dieser Hardwarekonfiguration nicht ausführbar AH=$03 (Funktion unzulässig im aktuellen Grafikmodus) (Diese Meldungen gibt es auch für jede andere INT 10, AX=$4Fxx (also VESA) Funktion.) Danach stehen in dem Buffer die folgenden Informationen: Offset Größe Beschreibung $00 DWORD Signatur "VESA" (also 86,69,83,65 - hex $56,$45,$53,$41) $04 BYTE VESA version Nachkomma $05 BYTE VESA version Vorkomma $06 DWORD Pointer auf einen String, der den Hersteller angibt (nullterminiert!) $0A DWORD Flags, die die Fähigkeiten der GraKa angeben (siehe FLAGS) $0E DWORD Pointer auf die Liste der VESA modes, jeder Mode ist ein WORD. Ende der Liste mit $FFFF $12 WORD Größe des Grafikspeichers in 64k-Einheiten (Beispiel: 16 entspricht 16*65536=1048576, also 1 MB) $14-$FF sind bei VESA Mode unter 2.0 reserviert. Ab 2.0 sind diese: $14 BYTE Software Version Nachkomma (im BCD Format) $15 BYTE Software Version Vorkomma (im BCD Format) $16 DWORD Pointer auf Herstellername (nullterminiert!) $1A DWORD Pointer auf den Produktnamen (nullterminiert!) $1E DWORD Pointer auf Produkt-Revisions-String (eventuell Sub-Version) (nullterminiert!) $22 BYTE VBE/AF Version Nachkomma (im BCD Format) $23 BYTE VBE/AF Version Vorkomma (im BCD Format) (VBE/AF nur gültig wenn in FLAGS das Bit 3 gesetzt ist) $24 DWORD Pointer auf VBE/AF Grafikmode-Liste, ebenfalls Liste von Words, ebenfalls mit $FFFF beendet. Nur gültig, wenn in FLAGS das Bit 3 gesetzt ist. $28-$FF - reserviert - $100-$1FF 256 Bytes reserviert, hier stehen dann diverse Strings etc. Die FLAGS (DWORD ab $0A bis $0D, siehe oben) Bit(s) Beschreibung 0 DAC (Digital-Analog-Controller) kann in 8-bit-Mode geschaltet werden (Aus Gründen der Kompatibiltät sind die R-G-B Werde der Farben in den Paletten-Modes nur 6-Bit (wie bei VGA), obere 2 Bit unbenutzt. Ist dieses Bit gesetzt, so kann mit INT $10, AX=$4F08, BX=$0800 die Bitbreite der Farben auf 8 geschaltet werden. Damit hat man dann statt 256 aus 262144 die wirklichen 256 aus 16777216 Farben (24bit). 1 Wenn gesetzt, dann ist dies ein Non-VGA-Controller. Weiß nicht genau, was der Künstler uns damit sagen will - vermutlich, daß die normalen VGA-Modi NICHT oder nur sehr eingeschränkt verfügbar sind. 2 Wenn gesetzt, dann wird die Palette nur während des Rasterstahl- Rücklaufs (Vertical Retrace) neu gesetzt. Das verhindert Farbflackern. 3 Support für VBE/AF und (wenn VESA Version >=3.0) Stereo ("Hardware-3D") 4 Ab VESA v3.0 und wenn Bit 3 gesetzt: =0 "Stereo" Signal mit externem VESA Stereo Anschluß =1 "stereo" signal mit VESA EVC Anschluß ... (VBE/AF v1.0P) Muß EnableDirectAccess aufrufen, um Framebuffer anzusprechen 5 (VBE/AF v1.0P) Unterstützt hardwaremäßigen Mauspfeil 6 (VBE/AF v1.0P) Unterstützt hardwaremäßiges Clipping (?) 7 (VBE/AF v1.0P) Unterstützt hardwaremäßigen transparentes BitBLT (?) 8-31 reserviert (immer =0) Der Mode-Info-Block (Anmerkung: Diese Informationen sind aus der "Ralph Brown's Interrupt List" entnommen und von mir übersetzt worden (mit Erklärungen).) Um den Mode-Info-Block zu erhalten, sind 256 Bytes Speicher als Puffer zu reservieren, in den diese Informationen geschrieben werden. Der Aufruf sieht wie folgt aus: mov AX,$4F01 mov CX,Mode-Nummer (Nummer des VESA-Modes) LES DI,Adresse-des-Puffers (256 Bytes) int $10 Die Mode-Nummer sind die unteren 9 Bits des WORDS, wobei $0xx (also 0-255) VGA-Nodes sind und $1xx (also 256-511) sind VESA-Modes. Die Bits 15 bis 9 sind wie folgt belegt (für Setzen des Modes oder auch für diese Node-Prüfung: Bit(s) Beschreibung 15 1= Grafikspeicher NICHT löschen, wenn Mode gesetzt 14 1= (ab VESA v2.0) Linear-Framebuffer-Mode benutzen (Flat-Mode) 13 1= (wenn VBE/AF 1.0P) VBE/AF initialisiert Hardwarebeschleunigung 12 - reserviert für VBE/AF 11 1= (ab VESA v3.0) Benutzerdefinierte Bildrate ermöglichen 10-9 - reserviert für künftige Erweiterungen, immer =0 - 8-0 Modus-Nummer Danach steht in AL=$4F, wenn die Funktion unterstützt wird (sollte in jedem Fall unterstützt sein.) Und AH=$00, wenn der Aufruf erfolgreich war und AH=$01, wenn nicht (z.B. wenn es diesen Mode nicht gibt). Die Liste der Modes erhält man mit der Mode-Availability Table. Offset Größe Beschreibung (Table 00079) $00 WORD MODE FLAGS (siehe MODE FLAGS) $02 BYTE Bank 0 Flags (bitweise, siehe BANK FLAGS) $03 BYTE Bank 1 Flags (bitweise, siehe BANK FLAGS) $04 WORD Bank "Granularität" in KB, (normal heutzutage 64) $06 WORD Bank Größe in KB, (normal heutzutage 64) (Eigentlich sind Granularität und Größe immer gleich. Granularität gibt den Abstand der Banken voneinander an, Größe die Größe der Bank, also wieviele Adressen sie hat. Granularität kann daher nie größer als Bankgröße sein, sonst wären manche Bereiche ja nicht ansprechbar.) $08 WORD Segment für Bank 0 (normal $A000), 0, wenn nicht vorhanden $0A WORD Segment für Bank 1 (normal $A000), 0, wenn nicht vorhanden (Anmerkung: Habe auch schon gesehen, daß Bank 1 an Segment $B000 lag und beide Banken Schreib/Lese-fähig waren. Sowas ist natürlich dann schon Superklasse.) $0C DWORD Direkter Pointer auf die Routine, die die Bank umschaltet. Entspricht dem INT $10, AX=$4F05 Aufruf, mit: BX=Bank(0/1), DX=Bank-Nr $10 WORD Länge der Scanlinie in Bytes. Beispiel: bei 640x480,8bit ist diese 640 bei 640x480,16bit ist diese 1280 Anmerkung: Die Scanlinie kann auch unter Umständen länger sein als der für die Pixel benötigte Platz. Siehe restlicher Text. $12 WORD Breite in Pixeln (Grafikmodes) oder Zeichen (Textmode) $14 WORD Höhe in Pixeln (Grafikmodes) oder Zeichen (Textmode) $16 BYTE Breite eines Zeichens in Pixeln (Spalten) $17 BYTE Höhe eines Zeichens in Pixeln (Zeilen) $18 BYTE Anzahl "Ebenen". Normal=1. Bei 4bit-VGA sind es 4. $19 BYTE Bits pro Pixel (normalerweise 4,8,15,16,24 oder 32) $1A BYTE Anzahl Banken $1B BYTE Speicher-Anordnung (richtet sich nach dem Grafikmode) (siehe SPEICHER-ANORDNUNG) $1C BYTE Größe der aktiellen Bank in kByte $1D BYTE Anzahl Seiten-1, die bei dieser Auflösung/Pixelbits in den Grafikspeicher passen. $1E BYTE reserviert. Ist 0, wenn VESA v1 bis v2, ist 1, wenn VESA v3 Ab VESA v1.2 werden auch Hi/Truecolor-Modes unterstützt. Hier sind die Bitbreiten und Bitpositionen der Rot/Grün/Blau/"reserviert" Werte der Farben gespeichert. Ich gebe gleich die "normalen" Werte an für 15,16,24 und 32 bit Mode, die meistens benutzt werden (bisher keine andere Anordnung gesehen) Position = die Position des untersten Bits der Rot/Grün/Blau/reserviert-Bits. (15bit) (16bit) (24bit) (32bit) $1F BYTE Rot-Bits 5 5 8 8 $20 BYTE Rot-Position 10 11 16 16 $21 BYTE Grün-Bits 5 6 8 8 $22 BYTE Grün-Position 5 5 8 8 $23 BYTE Blau-Bits 5 5 8 8 $24 BYTE Blau-Position 0 0 0 0 $25 BYTE reserviert-Bits 1/0 0 0 8/0 $26 BYTE reserviert-Position 15/0 0 0 24/0 $27 BYTE Flags für Hi/True-Color-Modes: bit 0 =1 Farb-Bits/Position ist programmierbar (änderbar) bit 1 =1 Die "reserved" Bits/Bytes können vom Programmierer frei benutzt werden. Ab VESA v2.0: ------------- $28 DWORD Absolute Speicheradresse (32bit!) des Linearen Framebuffers $2C DWORD Hier beginnt der Grafikkartenspeicher, der nicht zur Grafikanzeige benutzt werden kann ("offscreen memory"). $30 WORD Größe des "offscreen memory". Ab VESA v3.0: ------------- $32 WORD Länge der Scanlinie in linearen Modes (linear Framebuffer) $34 BYTE Anzahl Bilder-1 für "banked" Grafikmodes $35 BYTE Anzahl Bilder-1 für "Framebuffer" Grafikmodes $36 BYTE Lin.Framebuffer: Rot-Bits $37 BYTE Lin.Framebuffer: Rot-Position $38 BYTE Lin.Framebuffer: Grün-Bits $39 BYTE Lin.Framebuffer: Grün-Position $3A BYTE Lin.Framebuffer: Blau-Bits $3B BYTE Lin.Framebuffer: Blau-Position $3C BYTE Lin.Framebuffer: reserved-Bits $3D BYTE Lin.Framebuffer: reserved-Position $3E DWORD Maximale Pixel Clock für Grafikmodes, in Hz $42-$FF reserviert (immer =0) Anmerkung: Ab VESA 1.1 werden alle unbenutzten Bytes im Puffer automatisch auf 0 gesetzt. VESA 1.0 tut dies nicht, sondern läßt sie unverändert. Um kompatibel zu sein, sollte man also vielleicht vorher (vor dem Aufruf) den Puffer mit 0 löschen. Die MODE FLAGS: --------------- Bit(s) Bescheibung 0 Mode wird von dieser Hardware (und Konfiguration) unterstützt 1 Optionale Information verfügbar (immer =1 ab VESA 1.2) (betrifft die Bytes ab $12) 2 BIOS Ausgabe unterstützt (für normale BIOS Modes) 3 0=Monochrom, 1=Farbmode 4 0=Textmode, 1=Grafikmode Ab VESA v2.0: 5 Mode ist NICHT VGA-kompatibel 6 "Banked" mode NICHT unterstützt! 7 "Linear Framebuffer" Mode unterstützt 8 Double-Scan Mode verfügbar (z.B. 320x200 und 320x240) (Double-Scan scannt dieselbe Zeile zweimal, so daß z.B. aus einem 320x480 Mode ein 320x240 Mode wird.) Ab VESA v3.0: 9 Interlaced Mode verfügbar (wie beim PAL TV: Es wird nur bei jedem Frame jede 2. Zeile angezeigt, immer im Wechsel die geraden und ungeraden Zeilen) 10 Hardware unterstützt Triple Buffering (3 Bilder im Wechsel) 11 Hardware unterstützt Stereoscopic Display (3D für "Shutter Glasses") 12 Unterstützt Dual Display Startadresse (für 2 Bildschirme). 13-15 - reserviert - Wenn VBE/AF v1.0P: 9 Programm muß EnableDirectAccess aufrufen, bevor es Bank-Wechsel- Funktionen aufruft Die BANK FLAGS: --------------- Wie schon erwähnt, die unteren 3 Bits geben an, ob die Bank existiert und ob sie lesbar und beschreibbar ist: Bit(s) Beschreinung 0 Bank ist vorhanden 1 Bank ist lesbar (kann ausgelesen werden) 2 Bank ist beschreibar 3-7 - reserviert - Die SPEICHER-ANORDNUNG: ----------------------- Dies sind normale Byte-Werte, die angeben, wie der Speicher aufgeteilt ist: 00h Textmode (1 Word pro Zeichen: 4bit Hintergr.,4bit Farbe, 8bit Zeichen) 01h CGA Mode (siehe dort) 02h "Herules Mono" Mode (siehe dort) 03h EGA Mode, 16-Farben (siehe dort) 04h "packed pixel" Mode (MCGA, mit Palette), (siehe dort) 05h 8bit (256 Farben), linear Mode 06h "direct color" (HiColor, TrueColor) Mode (also 15/16/24/32 Bit Mode) 07h YUV (luminance-chrominance, auch YIQ genannt) Mode. Spezial-TV-Mode 08h-0Fh - reserviert für VESA - 10h-FFh - OEM memory models - spezielle unstandardisierte Speichermodelle - ****************************************************************************** Anmerkung: Wenn man beim Setzen der VGA-Modi deren oberes Bit setzt (also statt $93 statt $13), wird beim Setzen des Modus der Grafikspeicher nicht gelöscht. Dasselbe gilt für VESA, nur daß hier das obere Bit im 16-Bit Wert gesetzt werden muß - also nicht $80, sondern $8000 zum Modus addiert werden muß. (also $8115 statt $0115). Setzt man VGA-Modi über den VESA-Befehl ist hier die VESA-Methode (also + $8000) zu benutzen - die VGA-Methode funktioniert hier dann nicht. Die Palette wird in jedem Fall immer neu auf die "Standard-Palette" gesetzt, wenn man den Grafikmode ändert (gilt natürlich nur für Modi, die auch Paletten benutzen - also z.B. nicht die 15/16/24/32-Bit Modi, die ohne Palette arbeiten und die Pixelfarbwerte direkt aus dem Speicher lesen. Das ist erstmal alles zur groben Theorie, wie Grafikmodi aufgebaut sind und wie sie funktionieren. Auch das Setzen eines Pixels sollte damit erst einmal möglich sein. Ich hoffe, ich habe nichts wichtiges vergessen. Erklärung von Funktionen wie: - Effektives Pixelsetzen - Effektives Linienziehen - Setzen von gefüllten und leeren Rechtecken - Setzen von gefüllten und leeren Dreiecken - Setzen von gefüllten und leeren Kreisen und Ellipsen - Setzen von gefüllten und leeren Polygonen - Setzen von grafischer Schrift - "Fixed Fonts" (also Schriftarten mit gleichbreiten Buchstaben) - "Proportional Fonts" (also Schriftarten, bei denen das große W sehr breit, das kleine i dagegen sehr schmal ist) - Setzen von "Figuren" (also Icons, "Sprites", Mauspfeile) - Benutzung von Dingen wie "Transparenz" und "Schatten". - Das alles für VGA, VESA und "tweaked VGA", auch bekannt als "Mode-X". folgen in einem weiteren, von diesem getrennten Tutorial. Desweiteren werde ich dort die VESA-Funktionen ausführlicher erläutern. Die im letzten GRAFIK.TXT angekündigten Funktionen $4F00 und $4F01 sind in DIESEM TEXT bereits enthalten. Zur Programmierung von VESA-Modi und der Benutzung von INTs (speziell INT $10 für Grafik) empfehle ich "Ralph Brown's Interrupt List". In ASM86FAQ.TXT ist viel zum Thema Assembler erklärt. Sie enthält auch einen gesonderten Abschnitt zur Benutzung des ominösen, aber beliebten und nützlichen "Mode-X". Zum Thema Mode-X und Grafikkartenregister werde ich evtl ein weiteres, getrenntes Tutorial verfassen, das über die - hier nur angerissenen - Punkte hinausgeht. Für Fehler in diesem Text übernehme ich keinerlei Haftung. Ich bin auch nur ein Mensch. Ich kann mich mal verschreiben. Ich kann mich mal irren. Meine Website: http://www.imperial-games.de Xpyder (Imperial Games), 2. 8. 2005 Text geändert am: 29. 6. 2006 (Grund: Farbreihenfolge für 15/16/24/32-Bit-Modi richtiggestellt. Einige Tippfehler entfernt. Anzahl Bildseiten im CGA richtiggestellt. An einigen Stellen das (sich eigentlich selbst verstehende) INT $10 noch eingefügt.) Text geändert am: 28. 1. 2010 (Grund: Fehler bei VESA Schreib-/Lesezugriff-Doku. Die ATI-Variante ist kein "Bug", sondern ein Feature. Außerdem: Funktionen für Grafikkarten-Fähigkeiten ($4F00) und Mode-Info-Block ($4F01) hinzugefügt.