Grafik für Profis (Teil 2)
Im Verlauf dieses Kurses bekommen Sie ein professionelles Grafikprogramm, mit dem es sich hervorragend arbeiten läßt.

Profi-Grafik 64 besteht aus vielerlei Grafik-Routinen, die zu einer Basic-Erweiterung zusammengefaßt wurden, um das Programm leichter handhabbar zu machen. Profi-Grafik 64 stellt zwei Bildschirmseiten bereit, Multicolor-Grafik ist ohne Einschränkung verfügbar, bis zu acht Sprites bewegen sich gleichzeitig (interruptgesteuert) über den Bildschirm und sogar 3-D-Grafik wird durch ganz einfache Befehle realisiert.
In der ersten Folge von »Grafik für Profis« (64'er 5/86) haben Sie bereits die Befehle kennengelernt, die für die Inbetriebnahme der hochauflösenden Grafik grundlegend sind. In Listing 1 haben wir das Programm zu diesen neun Routinen noch einmal abgedruckt.
PROGRAMM : PG64 8390 8574 ----------------------------------- 8390 : 20 9E B7 E0 02 90 03 4C 53 8398 : 48 B2 BD A1 83 8D F1 9F 88 83A0 : 60 A0 E0 AD 00 DD 29 FC CC 83A8 : 2C F1 9F 70 02 09 01 8D 4A 83B0 : 00 DD AD 18 D0 09 28 8D 1E 83B8 : 18 D0 20 EA 83 AD 11 D0 29 83C0 : 09 20 8D 11 D0 60 20 A3 37 83C8 : 83 AD 16 D0 09 10 8D 16 35 83D0 : D0 60 AD 00 DD 09 03 8D 89 83D8 : 00 DD AD 18 D0 29 D7 8D 06 83E0 : 18 D0 AD 11 D0 29 DF 8D DF 83E8 : 11 D0 AD 16 D0 29 EF 8D C1 83F0 : 16 D0 60 AD F1 9F 85 21 B0 83F8 : A9 00 85 20 A8 A2 20 91 4A 8400 : 20 C8 D0 FB E6 21 CA D0 7C 8408 : F6 60 20 9E B7 86 20 20 7B 8410 : FD AE 20 9E B7 86 21 A5 C0 8418 : 20 0A 0A 0A 0A 18 65 21 3A 8420 : 20 35 84 20 79 00 C9 2C 17 8428 : D0 27 20 73 00 20 9E B7 ED 8430 : 8A A2 D8 D0 0A 2C F1 9F 65 8438 : 70 03 A2 8C 2C A2 CC 86 7C 8440 : 21 A0 00 84 20 A2 04 91 8C 8448 : 20 C8 D0 FB E6 21 CA D0 C4 8450 : F6 60 20 9E B7 E0 03 90 02 8458 : 03 4C 48 B2 BD 63 84 8D 0E 8460 : F2 9F 60 00 40 80 20 9E 00 8468 : B7 E0 04 B0 EC 8E F3 9F F9 8470 : 60 4A 4A 4A A8 18 8A 29 99 8478 : 07 79 32 85 85 F7 A5 14 50 8480 : 29 F8 65 F7 85 F7 B9 4B 13 8488 : 85 6D F1 9F 65 15 85 F8 3B 8490 : A5 14 29 07 A8 B9 64 85 60 8498 : 60 4A 4A 4A A8 A5 14 29 54 84A0 : FC 0A 85 F7 B9 4B 85 6D E8 84A8 : F1 9F 85 F8 8A 29 07 79 EA 84B0 : 32 85 A8 A5 14 29 03 AA 70 84B8 : BD 6C 85 38 60 20 EB B7 3A 84C0 : AD 16 D0 29 10 D0 28 E0 BC 84C8 : C8 B0 F1 A4 15 F0 09 88 07 84D0 : D0 E9 A5 14 C9 40 B0 E4 AC 84D8 : 78 A9 34 85 01 8A 48 20 A8 84E0 : 71 84 A0 00 2C F2 9F 70 75 84E8 : 37 30 3A 11 F7 D0 38 E0 91 84F0 : C8 B0 C9 A5 15 D0 C4 A5 6E 84F8 : 14 C9 A0 B0 BE 78 A9 34 EE 8500 : 85 01 8A 48 20 99 84 2C EB 8508 : F2 9F 70 14 30 17 48 49 D8 8510 : FF 31 F7 91 F7 AE F3 9F DC 8518 : 68 3D 70 85 11 F7 D0 07 0E 8520 : 49 FF 31 F7 2C 51 F7 91 04 8528 : F7 68 AA A9 37 85 01 58 87 8530 : 18 60 00 40 80 C0 00 40 0F 8538 : 80 C0 00 40 80 C0 00 40 AF 8540 : 80 C0 00 40 80 C0 00 40 B7 8548 : 80 C0 00 00 01 02 03 05 5F 8550 : 06 07 08 0A 0B 0C 0D 0F 81 8558 : 10 11 12 14 15 16 17 19 89 8560 : 1A 1B 1C 1E 80 40 20 10 7D 8568 : 08 04 02 01 C0 30 0C 03 D7 8570 : 00 55 AA FF 5D
Diese Routinen leisten (ganz kurz skizziert) folgendes:
SCREEN nr. (bestimmt die Nummer des Bildschirms, den man anwählen will)
HIRES (schaltet den mit SCREEN festgelegten Bildschirm ein)
MULTI (schaltet den Multicolor-Modus ein)
TEXT (schaltet auf den Textbildschirm zurück)
CLEAR (löscht die Bitmap des angewählten Bildschirms) HICOL zf,hf (,c3) (setzt die Farben im Video-RAM des angewählten Bildschirms)
MODE m (verändert die Wirkung des PLOT-Befehl)
INK co (legt die Zeichenfarbe im Multicolor-Modus fest)
PLOT x,y (setzt, löscht oder inventiert das Bit »x,y« in der Bitmap)
Diese »PLOT«-Routine ist ein Kernstück jedes Grafikprogramms, das über seinen Erfolg und Mißerfolg mitentscheidet. Wir sind in der letzten Folge ausgiebig darauf eingegangen, wie man mit dem Befehl »PLOT« arbeitet. In diesem Zusammenhang haben wir den Aufbau der Bitmap erklärt sowie auf ihre unterschiedliche Belegung im Hi-Res- und im Multicolor-Modus.
Außer den Grafik-Befehlen stellt das Programm Ihnen noch ein Mini-Toolkit (OLD (holt ein gelöschtes Programm wieder) und AUTO znr,sw (übernimmt die automatische Zeilennumerierung von Zeilennummer znr mit der Schrittweite sw von 0 bis 255)) zur Verfügung.
Profi-Grafik 64 ist portabel!
Ab dieser zweiten Folge des Grafikkurses werden nur die höheren Zeichenfunktionen behandelt, die mit der Hardware des Computers nichts mehr zu tun haben, sondern die reine Softwarelösungen sind. Man könnte diese Routinen also prinzipiell ohne großen Aufwand auf andere Computer, die mit dem 6502(6510)-Prozessor arbeiten, übertragen.
Die Reihe der Grafikbefehle wird fortgesetzt mit dem LINE-Befehl. Eine Linie wird auf dem Grafikbildschirm gezogen. Dazu wurde ein sehr eleganter und kompakter Algorithmus realisiert, der nichtsdestoweniger eine hohe Ausführungsgeschwindigkeit aufweist. Das war Listing 2; in der 64'er, 5/86, Seite 29 abgedruckt. Die Wirkungsweise wird durch einen Programmablaufplan illustriert (Bild 1).

So funktioniert LINE
LINE X1, Y1, X2, Y2
So ruft man die Routine LINE auf. Aber wie arbeitet diese Routine denn nun?
Um eine Linie zwischen zwei Punkten zu ziehen, müssen natürlich zuerst die Koordinaten der beiden Punkte eingelesen werden. Diese werden in den Variablen XlL, XlH, Y1 beziehungsweise X2L, X2H, Y2 abgelegt. Eine Gerade in der Zweipunkteform ist mathematisch durch folgende Gleichung festgelegt:
Y = M * ((Y2-Y1)/(X2-X1)) * X
Der Term vor dem X gibt dabei die Steigung an. Um diese Gleichung in Assembler zu formulieren, könnte man die Differenzen (Y2-Y1) und (X2-X1) bilden, den Quotient der Differenzen ausrechnen (16-Bit-Division) und in einer Schleife von XI bis X2 den Quotient mit dem jeweiligen X-Wert multiplizieren (16-Bit-Multiplikation), um so den gesuchten Y-Wert zu erhalten. Nun stünde der Programmierer vor dem Problem, eine 16-Bit-Division und Multiplikation in Maschinensprache zu formulieren.
Und vor allen Dingen viel zu langsam! Es geht aber auch anders, wenn man sich einiger mathematischer Grundlagen erinnert, die besagen, daß man eine Division auf eine Subtraktion und eine Multiplikation auf eine Addition zurückführen kann. So läßt sich der Ausdruck
(Y2 - Y1)/(X2 - X1)
auch ausdrücken durch
(Y2-Y1)-(X2-X1) + REST.
Um den Wert von Y zu erhalten, subtrahiert man (X2-X1) so oft von (Y2-Y1), bis der Rest kleiner wird als Null — also genauso, wie man dies bei handschriftlicher Division auch machen würde.
Beispiel: angenommen (Y2-Y1)= 150 und (X2-Xl) = 50, dann ist (Y2-Yl)/(X2-Xl) = 150/50 = 3 oder (Y2-Y1)/(X2-X1) (Y2-Yl)-(X2-Xl)-(X2-Xl)-(X2-Xl) + O(Rest)
(In dieser Gleichung bezeichnet O(Rest) eine Größe, die so klein wird, daß sie nicht mehr ins Gewicht fällt und vernachläßigt werden kann.)
Wollte man eine Gerade mit dieser Steigung zeichnen, müßte man jedesmal, wenn man auf der X-Ächse eine Einheit nach rechts geht, auf der Y-Achse vier Einheiten nach oben gehen. Oder man muß eine Einheit nach rechts gehen, wenn man auf der Y-Achse vier Einheiten nach oben gegangen ist.
Dieses Verfahren wird in der LINE-Routine (fast) genauso umgesetzt.
Wenn Sie sich den Programm-Ablauf-Plan ansehen, werden Sie innerhalb der Schleife eine Abfrage REST<0? entdecken. Ist REST > 0, dann wird der REST um (X2-X1) vermindert und gleichzeitig der Y-Zähler um eins erhöht. Dann wird der Punkt gesetzt… Der Y-Zähler wird so lange erhöht, bis REST < 0 ist. Ist dies der Fall, wird der X-Zähler erhöht und (Y2-Y1) zum REST addiert, was einer Multiplikation mit einem um eins erhöhten X-Zähler entspricht: (X + 1) * (Y2-Y1) = X * (Y2-Y1) + (Y2-Y1)
Die Schleife wird so lange durchlaufen, bis Anfangs- und Zielkoordinaten übereinstimmen.
Nun finden sich in der Routine aber noch einige andere Dinge. Ist die Xl-Koordinate größer als X2, dann wird (X2-X1) negativ, was bedeutet, daß nicht von links nach rechts, sondern von rechts nach links gezeichnet werden soll. In diesem Fall wird der X-Additionszeiger auf -1 gestellt und (X2-X1) negiert, damit die Differenz wieder positiv wird (wichtig für die Subtraktion in der Schleife). Desgleichen wird der Y-Additionszeiger auf-1 gestellt und (Y2-Y1) negiert, wenn nicht von oben nach unten, sondern von unten nach oben gezeichnet werden soll.
Ein Zeiger namens Groeko
Ein weiterer merkwürdiger Zeiger namens »Groeko« dient dazu, überflüssige Schleifendurchläufe zu vermeiden. Nehmen wir an, (X2-X1) sei größer als (Y2-Y1) und damit Groeko = 1. Weiterhin soll innerhalb der Schleife REST < 0 sein.
In diesem Fall wird der Y-Zähler um eins erhöht und REST um (X2-X1) erniedrigt (REST ist jetzt < 0). Da Groeko > 0 ist, ergibt die folgende Abfrage dieses Zeigers: die innere Schleife muß noch einmal durchlaufen werden. Jetzt wird (weil ja REST < 0) der X-Zähler auch noch um eins erhöht, bevor der Punkt gesetzt wird. Sie sehen in Bild 2 illustriert, wie die Routine sich mit und ohne Groeko-Abfrage verhält.

Hier sehen Sie deutlich: Ohne den Groeko-Zeiger werden wesentlich mehr Schleifendurchläufe benötigt (und damit mehr Punkte gesetzt), um ans Ziel zu gelangen. Die Linien werden dichter und etwas eckiger gezeichnet. Die Groeko-Abfrage spart also eine Menge Zeit.
So, damit dürfte die Funktionsweise der LINE-Routine hinreichend erklärt sein. Nun folgen noch zwei einfache Befehle, die auf dem LINE-Befehl aufbauen.
Ein Viereck zeichnet man so:
REC X1,Y1,X2,Y2
Der REC-Befehl dient zum Zeichnen eines Rechtecks. Hier gibt es nicht viel zu erklären, die beiden Eckpunkte werden lediglich durch vier Linien miteinander verbunden.
So füllt man das Kästchen:
BOX X1,Y1,X2,Y2
Mit BOX kann man ein ausgefülltes Rechteck darstellen. Dieser Befehl ist noch einfacher als der REC-Befehl. Es werden Y2-Y1 waagerechte Linien von XI bis X2 untereinander gezeichnet.
Mit diesen Befehlen läßt sich schon allerhand anfangen. Das Demoprogramm gibt spielerisch einen Einblick in die neugewonnenen Möglichkeiten.
Um die neuen Befehle in die Basic-Erweiterung (Listing 1 und 2 (Ausgabe 5/86) einzubinden, muß noch die Befehlstabelle um die neuen Wörter erweitert und die Adressentabelle ergänzt werden. Dies machen Sie am besten mit einem Monitor. Das Hexdump-Listing zeigt, was ergänzt werden muß:
:82B5 91 85 42 86 91 86 00 00
:831F 4C 49 4E C5 52 45 03 42
:8327 4FD8 00 00 00 00 00 00
Zu dieser Basic-Erweiterung gehören noch die folgenden Eingabe-Hinweise. Listing 2 (Ausgabe 5/86) wird zuerst mit dem MSE eingegeben und gespeichert. Danach wird das Programm in Listing 1 eingegeben und mit
LOAD "PG-MSE",8,1
wird jetzt Listing 2 dazugeladen. Mit einem Monitor muß dann der Speicherbereich von $8000 bis $8574 gespeichert werden. Und durch
SYS64738
wird das Programm aktiviert.
(Andreas Schömann/cg/og)