★ APPLICATIONS ★ DIVERS ★ Entwicklung einer Window-Load- bzw. Window-Save-Routine ★ |
Window-Basic (Schneider Magazin) | Applications Divers |
Vorliegende Window-Load- bzw. Window-Save-Routine soll es Ihnen ermöglichen, Windows zu definieren und danach ins RAM zu kopieren. Mit den Befehlen, die dann später in Form einer RSX-Erweiterung vorliegen werden, ist also eine Pull-Down-Menü-Programmierung recht einfach. Die Idee dazu bot mir der Aufbau des Bildschirmspeichers der CPC-Typen. Durch seine Verfügbarkeit im RAM lassen sich spielend leicht Teile verändern bzw. kopieren. Wie beginnt man nun bei einer solchen Programmierung? Zunächst muß man sich im klaren sein, welche Befehle mit welcher Funktion man haben möchte. Folgende sollen mit Dokumentation realisiert werden: |WIN.DEF, Nr., links, rechts, oben, unten soll mit Hilfe der üblichen Window-Koordinaten insgesamt acht Fenster definieren. |WIN.LOAD, Nr., Adr. soll das Window vom RAM auf den Screen bringen. |WIN.SAVE, Nr., Adr. soll das Window vom Screen ins RAM speichern. Betrachten wir zunächst |WIN.DEF (gewünschtes Format: |WIN.DEF, Nr., links, rechts, oben, unten). Insgesamt soll man später acht verschiedene Windows definieren können, was für eine gelungene Programmierung durchaus genug ist. Um bei der späteren Verwendung der Befehle immer wieder auf die definierten Werte zurückgreifen zu können, ist es unerläßlich, eine Tabelle anzulegen, die die Werte dauerhaft im RAM speichert. Durch eine dafür entwickelte Berechnungsroutine müssen die für das Maschinenprogramm wichtigen Adressen der Daten ermittelt werden. Da die Startadresse der Tabelle fix ist, kann man, wenn im Akku die Window-Nummer (0-7) steht und die Tabelle insgesamt 32 Werte (8 Windos * 4 Werte/Window) enthält, folgenden Algorithmus anwenden und dann in Assembler umsetzen: ADR = Basis + 4 * Akkuinhalt Bei der Realisierung der Gleichung muß man sich nicht mit der Integer-Arithmetik herumschlagen, sondern kann sich die Sache auch leicht machen:
So weit also zur Adressenberechnung für die Tabelle; damit wäre auch schon der Großteil unserer |WIN.DEF-Routine erledigt. Wer sich schon einmal mit den Assemblerkursen im Schneider Magazin beschäftigt hat, dürfte bei der RSX-Programmierung eigentlich keine Schwierigkeiten haben. Daß man mit Hilfe von (IX + Distanz) die übergebenen Parameter ausliest, wird bei der weiteren Entwicklung unseres kleinen ”WindowBasics” vorausgesetzt. Man muß also nur noch die einzelnen Parameter abfragen und dann der Tabelle übergeben. Vollständig läßt sich die Routine im Assemblerlisting betrachten. Nun kommen wir zu den beiden Hauptbefehlen |WIN.LOAD und |WIN.SAVE. Zunächst muß man sich den Aufbau des Bildschirmspeichers ins Gedächtnis zurückrufen: Eigentlich kann man dort nur über 16000 Bytes verfügen, wenngleich der Bildschirmspeicher aus 16384 Speicherzellen besteht. Die restlichen 384 Bytes sind die sogenannten Blanks. Die erwähnten 16000 Bytes teilen sich in 200 auf der Y-Achse und 80 auf der X-Achse. Diese Anordnung von 200 x 80 Bytes stellt das logische Koordinatensystem des Bildschirms dar. Logisch heißt es deshalb, weil man auf dem Screen auch 25 x 80 Cursor-Stellen ansprechen kann, die jeweils 8 Bytes benötigen und so die Zahl 16000 ergeben. Kommen wir zu den Befehlen zurück. Zuerst wird eine Routine benötigt, welche die erforderlichen Daten, die die Tabelle zur Verfügung stellt, für uns zu brauchbaren Werten aufbereitet, sprich linke obere Ecke und die Höhe bzw. die Breite. Das das Hilfsprogramm viel mit Mathematik zu tun haben wird, muß man zunächst eine Gleichung (wie bei der Tabelle) aufstellen, welche die Window-Koordinaten in physikalische Bildschirmkoordinaten umrechnet. Danach kann man einfach die etwas langsame, aber durchaus nützliche SCR DOT POSITION (s. Assemblerkurs 6/87) anspringen, um dann die Bildschirmadresse der linken oberen Koordinate zu erhalten. Nun der Algorithmus: Höhe (Bytes) = (UNTEN-OBEN) *8 Nach der Berechnung von ADR (x,y) muß nur noch SCR DOT POSITION angesprungen werden. In den aufgeführten Gleichungen bedeuten links, rechts, oben und unten die durch |WIN.DEF übergebenen Parameter. Durch sie werden Höhe, Breite und Bildschirmadresse (x,y) ermittelt. Mit Hilfe dieser Formeln erhält man die für die weitere Verwendung nötigen Daten. Die Berechnung in Maschinensprache wird später im Programm durch die Assembler-Kommandos ADD und SBC realisiert. Zum besseren Verständnis noch ein paar zusätzliche Erläuterungen: Die Berechnung von A * 8 wird durch den dreimaligen Befehl ADD A,A bzw. ADD HL,HL ausgedrückt. (Zum Vergleich sollte man immereinen Blick auf das Assemblerlisting werfen.) Der Trick besteht also darin, A * 8 nicht durch achtmaliges Aufaddieren von A umzusetzen, sondern den Wert einfach zu verdoppeln. Dies kommt der mathematischen Form 2 gleich, wobei n die Anzahl der ADD-A,A- bzw. ADD-HL,HL-Schritte ist. Möchte man nun jedoch fünfmal einen Wert im Akku multiplizieren, funktioniert diese Methode anfänglich nicht. Da 5 * A jedoch A * 2 + A ist, kann man diese Formel auch leicht in Maschinensprache umsetzen. In Assembler würde das dann so aussehen:
Nachdem wir nun alle nötigen Werte für den Transfer der Daten haben, bleibt nur noch die Frage, wie dieser am einfachsten und vor allen Dingen am schnellsten geschieht. Auch hier bedienen wir uns einer kleinen Unterroutine, die wir schnell entwickeln werden und die ganz leicht aufgebaut ist. Bei ihr soll der Inhalt ab HL nach DE kopiert werden. C soll dabei die Breite des Windows enthalten und B analog dazu die Höhe. Folgende Routine löst die Aufgabe zufriedenstellend:
CALL 0BC26H ruft hierbei eine Routine im ROM (00C13H; RAM: 0BC26H) auf, welche die Bildschirmadresse eine Byte-Reihe nach unten rechnet. Um die Routine auch für den anderen Befehl verwenden zu können, muß man nur HL und DE vertauschen. Allen, die diese Routine weiterentwickeln wollen, sei gesagt, daß man nur in MODE 2 arbeiten kann. Mit der Routine SCR GET MODE läßt sich jedoch einiges anfangen. Zusätzlich ist es ja auch möglich, Rahmen usw. einzubauen; das geht aber schon fast in GEM-Bereiche. Assembler-Programmierer sollten sich einmal überlegen, wie man diese Routine verbessern, d.h. die Geschwindigkeit erhöhen könnte. Michael Arndt, Schneider Magazin
|