CODINGLISTINGS ★ WINDOW-ROUTINEN (CPC AMSTRAD INTERNATIONAL) ★

Der Bandwurm im Bildschirmspeicher (CPC Amstrad International '89/3)Von der Wiege bis zur Bahre: Formulare, Formulare. . . (CPC Amstrad International '89/4)
★ Ce texte vous est présenté dans sa version originale ★ 
 ★ This text is presented to you in its original version ★ 
 ★ Este texto se presenta en su versión original ★ 
 ★ Dieser Text wird in seiner Originalfassung präsentiert ★ 

Bereits in der letzten Folge der Assemblerecke wurden Routinen vorgestellt, die es ermöglichen, mit Bildschirmausschnitten zu operieren. Hat man sich erst einmal in das Adressenlabyrinth des Bildschirmspeichers hineingewagt und dort Fuß gefaßt, so ist es nur noch ein kleiner Schritt bis zur Programmierung der berühmten Pulldown-und Pop-Up-Menüfenster, die zu einem modernen Programmdesign einfach dazugehören. Diese Folge liefert die restlichen Bausteine, die Sie brauchen, um Ihren Programmen den gewissen 'professionellen Touch' zu verleihen.

Allerdings gehört zu der ganzen Angelegenheit auch etwas Bürokratie. Wenn ein Programm mit mehreren Fenstern operieren soll, braucht man solide Routinen, die zumindest einen Teil der Verwaltungsarbeit übernehmen.

Der erfahrene Programmierer macht sich hier keine Illusionen: Ohne gut sortierte Datenstrukturen landet man bald im Chaos. So sind z.B. nur etwa 10 Prozent eines durchschnittlichen Spielprogramms für die Bildschirmeffekte zuständig, der Rest ist vollauf damit beschäftigt, irgendwelche 'Formulare* im Speicher auszufüllen oder zu lesen.

Deshalb w'erden wir uns zunächst ein paar Gedanken darum machen, welche Art Formulare für unser Fenstersystem geeignet ist.

Sesam, öffne dich...

Eine Routine, die ein Fenster auf dem Bildschirm 'öffnet“, muß natürlich wissen, an welcher Stelle und in welcher Größe. Diese Informationen (die Fenstergrenzen in Textkoordinaten) werden als Parameter beim Aufruf übergeben und in Bildschirmadressen umgerechnet — dieses Problem haben wir bereits in der letzten Folge gelöst. Aufgabe unserer Spezial-Windowroutinen ist es jedoch auch, den durch das Fenster verdeckten Bildschirminhalt irgendwo abzuspeichern. Es muß also ein reservierter Speicherbereich zur Verfügung stehen und so geschickt verwaltet werden, daß bei mehreren gleichzeitig geöffneten Pulldown-Win-dows kein Chaos entsteht.

Auch die Routine, die ein Fenster 'schließt“, indem sie den ursprünglichen Zustand wiederherstellt, will eine Menge wissen: Wo wurde der Hintergrund abgespeichert? Aus welcher Bildschirmregion stammt er? Wie breit und wie hoch ist der Bereich? Diese Fragen lassen sich leicht beantworten, wenn für jedes geöffnete Fenster das folgende Formular ausgefüllt wird:

  1. Speicheradresse des Hintergrundes (2 Bytes)
  2. Bildschirmadresse der linken oberen Ecke (2 Bytes)
  3. Breite des Bereichs in Bytes (1 Byte)
  4. Höhe des Bereichs in Rasterzeilen (1 Byte)

Insgesamt enthält das Formular vier Einträge und belegt einen 6 Byte langen Datenblock. Die erste Angabe sollte schon zur Verfügung stehen, bevor das Fenster geöffnet wird, damit die zuständige Routine weiß, wo sie den Hintergrund ablegen kann. Sie könnte dann auf folgende Weise vorgehen:

  • Entnehme dem Formular die Adresse für den Hintergrund.
  • Berechne aus den Fenstergrenzen die restlichen Angaben und trage sie in das Formular ein.
  • Speichere den Hintergrund ab und fülle den Bildschirmbereich mit einer Farbe.
  • Trage die Startadresse des noch verbleibenden Hintergrunds.
  • Speichere es in das Formular für das nächste Fenster ein.

Ein Fenster sagt's dem nächsten...

Auf diese Weise haben wir bereits eine einfache Speicherverwaltung organisiert. Nur im ersten Formular müssen wir 'per Hand“ die Start-Speicheradresse für Bildhinlergriinde eintragen. Danach sagt quasi jedes Fenster dem nächsten Bescheid, wie es weitergeht.

Das Schließen eines Fensters ist nach diesen Vorbereitungen eine relativ einfache Angelegenheit:

  • Suche das für das Fenster zuständige Formular heraus.
  • Lese die Informationen.
  • Stelle den ursprünglichen Bildschirminhalt wieder her.

Wenn man die Angelegenheit genau durchdenkt, kommt man jedoch als-

bald ins Grübeln: Was ist eigentlich mit Fenstern, die sich gegenseitig überlappen? Angenommen, es wird ein Fenster geschlossen, das noch von einem anderen Fenster teilweise verdeckt wird... und an dieser Stelle wird es in der Tat ganz schön kompliziert. Doch da wir hier nicht unbedingt den Profis von Digital Research mit ihrer Benutzeroberfläche GEM Konkurrenz machen wollen (die haben schon genug Ärger mit Windows von Microsoft), werden wir eine Regel einführen, die die Fensterverwaltung wesentlich vereinfacht:

  • Fenster dürfen nur in der umgekehrten Reihenfolge geschlossen werden, in der sie geöffnet wurden.

Beim Öffnen der Fenster wird also eine Art Formularstapel angelegt, und die Schließroutine darf nur das jeweils oberste Formular herunternehmen und bearbeiten. Es ist ihr verboten, etwas mitten aus dem Stapel herauszuziehen. Dieses Prinzip wird in Fachkreisen LIFO genannt (Last In, First Out), und damit es funktioniert, brauchen wir noch ein Byte im Speicher, das angibt, wie viele Fenster zur Zeit geöffnet sind, oder anders gesagt, wie hoch der Stapel ist.

Und jetzt ein Blick auf das Assemblerlisting mit den neuen Routinen: Für die Teile aus der letzten Folge wird zur Orientierung nur der 'Header1 mit den Ein- und Aussprungbedingungen angegeben. Die Databox zu diesem Heft enthält jedoch den kompletten Assembler-Quellcode.

Von Basic aus werden die Routinen nicht direkt aufgerufen, sondern über eine Ansammlung von 'SprungVektoren1, die am Anfang des Listings stehen. Dieser kleine Umweg hat den Vorteil, daß man nach Änderungen in dem Maschinenprogramm nicht alle Basic-CALLs neu anpassen muß. Die Adressen der JP-Befehle bleiben stabil, auch wenn sich die Einsprungadressen der Routinen verschieben!

Ab Zeile 500 wird mit der Assemblerdirektive DS (Define Space) der Speicherplatz für die Formulare freigehalten. Ein Byte (Label ANZAHL) ist für die aktuelle Anzahl geöffneter Fenster vorgesehen; danach folgen 50 Bytes für 8 Formulare mit je 6 Bytes. Das System kann also maximal 8 geöffnete Fenster verkraften, was für den Hausgebrauch reichen dürfte. Die Reservierung von 50 statt 48 Bytes ist notwendig, da das 8. (letzte) Fenster noch eine Speicheradresse für das nächste Fenster eintragen will (s.o).

Eine Formel gegen Platzangst

Die Routine INITW ab Zeile 2000 dient dazu, die gesamte Fensterverwaltung zu initialisieren. Zunächst sollte der Speicherplatz berechnet werden, den die geretteten Bildhintergründe insgesamt benötigen. Dabei hilft folgende Formel:

Speicherplatz für ein Fenster = (unten-oben + 1)*8 * (rechts-links+1)*mf wobei mf der in der letzten Folge erwähnte MODE-Faktor ist (1 für MODE 2, 2 für MODE 1, 4 für MODE 2). Den Gesamt-Speicherplatz plus 1 zieht man von &A000 ab (dort beginnen die Window-Routinen) und erhält den erforderlichen HIMEM-Wert, der mit MEMORY festgelegt wird. Die INITW-Routine empfängt die Adresse per CALL initw,HIMEM +1, trägt sie in das erste Formular ein und setzt weiterhin die Anzahl der aktiven Fenster auf 0. Sehr wichtig: INITW muß einmalig zu Beginn eines Programms aufgerufen werden, bevor das erste Fenster geöffnet wird! Ansonsten gibt es mit Sicherheit grandiose Abstürze.

Die Routine OPENW ab Zeile 3000 besorgt sich zunächst mit CALL WINPAR wie in der letzten Folge beschrieben die Fenstergrenzen und berechnet daraus mit CALL WINADR die Bildschirmadresse und die Ausmaße in Bytes. Danach informiert sie sich über die Anzahl bereits geöffneter Fenster, nimmt den Wert mit 6 mal und addiert die Startadresse des 'Formularstapels1. Das Ergebnis, nämlich die Adresse des Formulars für das neue Fenster, wird in das Indexregister IY befördert (Zeile 3240), das einen einfachen Zugriff auf die Werte ermöglicht.

Nach dem Lesen und Schreiben des Formulars kümmert sich die Routine um die Farbe, mit der das Fenster gelöscht werden soll (Zeile 3340). Sinnvollerweise benutzt sie den aktuellen PAPER-Wert, der jedoch noch in ein Bitmuster umcodiert werden muß, das auf dem Bildschirm die entsprechende Farbe erzeugt. Diese komplizierte Aufgabe erledigen zwei Betriebssystemroutinen: TXT GET PAPER (&BB99) Input: Keine Bedingung Output: A enthält die aktuelle PAPER-Nummer SCR INK ENCODE (&BC2C) Input: A enthält eine Farbstiftnummer (PEN oder PAPER). Output: A enthält das codierte Farb-byte.
Beide Routinen verändern nur den Akku und die Flags; alle anderen Register bleiben erhalten.

Nachdem die Farbinformation 'mundgerecht* für den Videochip aufbereitet wurde, befördert eine doppelte Schleife ab Zeile 3370 die Bildschirmbytes in den Speicher und das Farbbyte ins Video-RAM. Da hier zwei Aufgaben (Hintergrund sichern, Fenster löschen) in einem Aufwasch erledigt werden, ist die Routine sehr schnell! Zum Abschluß bleibt ihr nur noch übrig, das Formular für das nächste Fenster vorzubereiten, und dann geht es zurück ins Basic.

Die Routine CLOSEW hat es danach sehr einfach: Ihr müssen beim Aufruf keine Fenstergrenzen übergeben werden, da sie ja alle Angaben einem Formular entnehmen kann. Nachdem sie die Variable ANZAHL um 1 vermindert hat, berechnet sie genau wie OPENW die Formularadresse, holt sich die Werte und schreibt den ursprünglichen Hintergrund zurück auf den Bildschirm.

Was das Demo verschweigt: Routinen mit Selbstmordtendenzen

Wer nachprüfen möchte, ob das Ganze auch funktioniert, kann zunächst das Basicdemoprogramm abtippen, das den kompletten Basiclader für die Window-Routinen als Unterprogramm zur Verfügung stellt. Über die Maschinenroutinen bleibt noch zu sagen, daß sie zwar gut funktionieren, aber noch lange keine Ideallösung darstellen.

Schön wäre z.B. eine Routine, die ein Fenster mit einem Rahmen versieht. Weiterhin fehlen noch reihenweise Sicherheitsabfragen. Wenn die Fenster mehr Speicherplatz benötigen, als vorgesehen wurde, so werden die Window-Routinen überschrieben und begehen damit quasi Selbstmord. Auch fehlt eine Sicherung gegen illegale Fenstergrenzen, was ebenfalls zum Absturz führen kann. Kurz gesagt: Das System ist in dieser Form nur für Programmierer geeignet, die wissen, was sie tun.

Allerdings ist es auch nicht Aufgabe der Assemblerecke, 'Black Box'-Komplettlösungen anzubieten. Deshalb: Werden Sie aktiv und bringen Sie das System zur Reife.

Matthias Uphoff/cd, CPCAI

★ PUBLISHER: CPC Amstrad International
★ YEAR: 1989
★ CONFIG: 64K + AMSDOS
★ LANGUAGE:
★ LiCENCE: LISTING
★ COLLECTIONS: CPC AMSTRAD INTERNATIONAL 1989 , CPC AMSTRAD INTERNATIONAL 1989
★ AUTHOR: Matthias Uphoff
 

★ AMSTRAD CPC ★ DOWNLOAD ★

Type-in/Listings:
» Window-Routinen    (CPC  Amstrad  International)    (Source)    GERMANDATE: 2020-06-23
DL: 209
TYPE: text
SiZE: 4Ko
NOTE:

» Window-Routinen    (CPC  Amstrad  International)    GERMANDATE: 2013-05-31
DL: 305
TYPE: ZIP
SiZE: 5Ko
NOTE: 40 Cyls
.HFE: Χ

★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser...

Lien(s):
» Applications » Windrad (AM-Mag)
» Applications » Trace in Windows
» Applications » Windows
» Applications » Windows Kasse
» Applications » Windowkey
» Applications » Window - Planer (CPC Amstrad International)
Je participe au site:
» Vous avez des infos personnel ?
» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

CPCrulez[Content Management System] v8.7-desktop
Page créée en 243 millisecondes et consultée 1439 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.