★ CODING ★ LISTINGS ★ Kleiner Punkt, großer Aufwand|CPC Amstrad International) ★ |
Fast-Plot (CPC Amstrad International) | Coding Listings |
Wissen Sie, was ein Pixel ist? Na klar - ein Pünktchen auf dem Bildschirm. Wissen Sie aber auch, woher dieser Begriff stammt? Es handelt sich um eine Verunkürzung von 'Picture ElementProfis sprechen sogar mitunter nur noch von einem Pel, um keine wertvollen Mikrosekunden mit der Aussprache von 'ix ' zu vergeuden. Und noch eine dumme Frage: Wie erzeugt man ein Pel auf dem CPC-Monitor? Ganz einfach, mit einem PLOT-Befehl... und wenn das CPC-Betriebssystem sprechen könnte, würde es jetzt energisch Protest einlegen: Von wegen einfach! Bereits in den letzten Folgen der As-semblerecke haben wir uns im Bildschirmspeicher herumgetrieben, dabei jedoch nur mit kompletten Bytes jongliert. Will man in Maschinensprache gezielt Punkte ansprechen, so müssen diese innerhalb eines Bytes lokalisiert werden, was neue Komplikationen mit sich bringt. Um der Sache näher zu kommen, schaut man sich am besten an, wie es das Betriebssystem macht. Damit Sie sich jedoch nicht mit ROM-Listings plagen müssen, finden Sie in dieser Folge ein Programm, das die Vorgehens weise in reinem Basic nachvollzieht. Die Zeilen 10 bis 90 dienen nur Testzwecken: Hier können Sie zwei Grafikkoordinaten x,y eingeben, um an der entsprechenden Stelle einen Punkt zu erzeugen. Ernst wird es in der Subroutine PLOT, die ab Zeile 130 zunächst die Legalität Ihrer Eingaben prüft. Koordinaten außerhalb des Bildschirms könnten sonst Punkte an irgendeiner Undefinierten Position erscheinen lassen. Physikalische Koordinaten und was davon zu halten ist Ab Zeile 170 erfolgt die Umrechnung in physikalische Koordinaten, und dazu ist erst einmal eine Erklärung fällig: Die Grafikkoordinaten des CPC reichen vertikal von 0 bis 399 und horizontal von 0 bis 639, was jcdoch nicht dem tatsächlichen Auflösungsvermögen entspricht. In Y-Richtung lassen sich nur 200 Punkte darstellen; in X-Richtung sind es 640 (MODE 2), 320 (MODE 1) oder gar nur 160 (MODE 0). Was auf den ersten Blick wie Lug und Betrug aussieht, ist jedoch eine Wohltat für den Basic-Programmierer: Unabhängig vom MODE erzeugen gleiche Zahlenwerte geometrisch gesehen die gleichen Ergebnisse. Weiterhin sind die X-und Y-Skalierungen so aufeinander abgestimmt, daß ein mathematisch exakter Kreis wirklich als Kreis auf dem Bildschirm erscheint und nicht als Ellipse. Natürlich muß sich das Betriebssystem an der physikalischen Realität orientieren und die Anwenderkoordinaten so umrechnen, daß sie der tatsächlichen Pixelanzahl entsprechen. Der Y-Wert wird deshalb durch 2 geteilt und der X-Wert in MODE 1 und MODE 0 durch 2 bzw. 4. Da es keine halben Pixel gibt, benutzt das Basic-Programm die Ganzzahl-Division ohne Rest (umgekehrter Schrägstrich). Der MODE wird einer Speicherstelle entnommen, die für den CPC 464 und CPC 664/6128 verschieden ist — hier bitte aufpassen! Für weitere Berechnungen wird in Zeile 240 die Anzahl der Pixel innerhalb eines Bildschirm-Bytes bestimmt, die je nach MODE verschieden ist. Die MODE-spezifischen Bitmasken helfen bei der Lokalisierung eines Punktes innerhalb eines Bytes — dazu gleich mehr. Das Statement y = 199-y in Zeile 290 stellt die Y-Achse quasi auf den Kopf und verlegt den Punkt 0,0 in die linke obere Ecke. Das ist eine weitere Anpassung an die physikalische Realität: In einem mathematischen Koordinatensystem wachsen die Y-Werte von unten nach oben; die Bildschirmadressen nehmen jedoch in umgekehrter Richtung zu! Adreßberechnungen Die Umrechnung der X/Y-Koordina-ten in eine Bildschirmadresse erfolgt in Zeile 300. Das Adressenlabyrinth des Video-RAMs wurde bereits in Heft 3/89 ausführlich besprochen. Hier soll nur das Wichtigste in Kürze wiederholt werden: Wenn nach dem letzten MODE-Befehl oder Reset kein Hardware-Scrolling (Rollen des gesamten Bildschirms) stattgefunden hat, liegt die linke obere Bildschirmecke an der Adresse &C000. Wandert man von dort aus jeweils eine Textzeile (8 Pixelreihen) nach unten, so erhöht sich die Adresse immer um 80. Innerhalb einer Textzeile bewirkt der Sprung zur nächsten Pixelreihe jedoch eine Erhöhung um 2048 (Hex &800). Mit diesen Erkenntnissen läßt sich die in Zeile 300 benutzte Formel aufschlüsseln: adr+&C000+(y \8)*80 ergibt die-Startadresse (links,oben) der Textzeile, in der sich der Punkt befindet. Die Ganzzahldivision ohne Rest rechnet hier die Y-Grafikkoordinate in die Textzeilen-Nummer um. adr=adr+(y MOD 8)*2048 rechnet die Adresse innerhalb der Textzeile mit Hilfe des Divisionsrestes nach unten weiter, um zu der korrekten Pixelreihe zu gelangen. adr=adr + (x ^ pb) rechnet schließlich die Adresse nach rechts bis zum richtigen Byte weiter, indem die X-Koordinate addiert wird. Natürlich muß sie vorher durch die Pixel pro Byte dividiert werden, da jedes Byte gleich mehrere Punkte enthält! Und damit befinden wir uns jetzt nahe genug an der Hardware, um uns wieder mit den Eigenarten des CPC-Video-chips herumärgern zu dürfen. Innerhalb eines Bytes sind bestimmte 'signifikante' Bits für unseren Punkt zuständig — aber welche? Wie Tabelle 1 zeigt, ist das in MODE 2 noch sehr einfach: Jedes Bit entspricht genau einem Bildpunkt. Steht das Bit auf 1, so wird der Punkt mit PEN 1 dargestellt, ansonsten mit PEN 0. Dabei muß man nur im Auge behalten, daß das höchstwertige Bit (Bit 7) für die Punktposition ganz links zuständig ist, Bit 6 für den nächsten Punkt usw. In MODE 1 werden 2 Bits pro Punkt benötigt, um die vier Farben von PEN 0 bis PEN 3 unterscheiden zu können. Wer jetzt allerdings glaubt, daß die beiden Bits ordentlich sortiert nebeneinander liegen, kennt unseren Videochip noch nicht! Die Organisation des Bildschirmspeichers ist nämlich total auf seine Hardware-Logik zugeschnitten; der Programmierer muß sich gefälligst damit abfinden, daß die Bits für einen Pixel fein säuberlich im Byte verteilt liegen. Der Tabelle können Sie entnehmen, welche Bits für welche Punktposition zuständig sind, und sich gleichzeitig davon überzeugen, daß das Chaos in MODE 0 noch größer wird (4 Bit pro Punkt für 16 Farben). Um die Bits gezielt anzusprechen, wurden bereits in den Basiczeilen 260-280 Bitmasken vorbereitet, die an den signifikanten Stellen eine 1 enthalten. In der vorliegenden Form gelten sie aller- Bits bekennen Farbe Wenn man die Bitmaske per OR-Ver-knüpfung in das Bildschirmbyte hineinmurkst, erhält man allerdings immer nur einen Punkt in der höchstmöglichen Farbnummer (z.B. PEN 3 in MODE 1). Was uns noch fehlt, ist die Codierung der Farben in den signifikanten Bits. Hierbei hilft wieder die Tabelle 1, in der die Bitnummern gleich in einer passenden Reihenfolge stehen. Dazu ein Beispiel: In MODE 0 soll ein Byte mit PEN 12 eingefärbt werden. Da die Zahl 12 im Binärsystem durch I 100 dargestellt wird, müssen die Bits für die beiden Punktpositionen auf folgende Weise gesetzt werden: Bit 1 = 1, Bit 5 = 1, Bit 3 = 0, Bit 7=0, Bit 0 = 1, Bit 4 = 1, Bit 2 = 0, Bit 6=0 Bringt man die Bits in die richtige Reihenfolge, so erhält man den Wert &X00110011. Solch ein Bitmuster, das für alle Punktpositionen in einem Byte die Farbe angibt, nennt man 'Farbmas-ke'. Überzeugen Sie sich selbst: Schal-
Nach einer Farbwahl mit PEN, PAPER usw. legt das Betriebssystem die dazugehörigen Farbmasken in bestimmten Speicherstellen ab (siehe Tabelle 2), damit sie für nachfolgende Bildschirmausgaben sofort zur Verfügung stehen. Normalerweise enthalten diese Masken für alle Punktpositionen die gleiche Farbe... es sei denn, ein hinterlistiger Mensch verbiegt hier ein paar Bits! Lassen Sie das folgende Kabinettstück auf Ihrem Rechner laufen: 10 'Farbmaskendemo |
CPC 464 | 664/6128 | |
PEN Grafik PAPER Grafik | &B338 &B339 | &B6A3 &B6A4 |
PEN Text PAPER Text | &B28F &B290 | &B72F &B730 |
aktueller MODE | &B1C8 | &B7C3 |
Tabelle 2: Speicherstellen für Farbmusken und den aktuellen MODE |
FASTPLOT. ASM:
Ganz schön schnell...
Es ist in der Tat erstaunlich kompliziert, einen einzigen Punkt zu erzeugen, wenn man auf den PLOT-Befehl und die Mithilfe des Betriebssystems verzichtet. Wer jedoch superschnelle Grafik in Maschinensprache programmieren will, kommt um dieses Grundlagenwissen nicht herum. Als Beispiel möchte ich Ihnen die FASTPLOT-Routine aus dem Fraktal-Generator vorstellen, die dazu beiträgt, die anspruchsvolle 3D-Grafik in akzeptabler Rechenzeit zu erzeugen. Hier wurde nach Kräften optimiert, was leider nicht der Übersichtlichkeit zugute kommt.
Sie können die Routine als 'Black Box' in eigenen Programmen einsetzen; wer jedoch herausfinden möchte, wie und warum sie funktioniert, wird sich eventuell die Zähne daran ausbeißen, obwohl im Prinzip das Gleiche wie im Basic-Listing ab Zeile 300 passiert.
Hier noch ein kleiner Tip: Die Basic-zeile 390 läßt sich nach den Gesetzen der Logik in das Äquivalent scrbyte = ((colmask XOR scrbyte) AND bit-mask) XOR scrbyte umformen, was sich in Assembler mit weniger Befehlen erledigen läßt — siehe Zeile 470 bis 500.
Immerhin ist die FASTPLOT-Routine sechsmal so schnell wie die Betriebssystem-Routine GRA PLOT, da sie sich auf MODE 1 beschränkt, keine Abfrage auf legale Werte enthält und gleich mit physikalischen Koordinaten angesteuert wird. Falls Sie es genau wissen wollen: FASTPLOT schafft 10500 Pixel pro Sekunde!
|
|