Turbo-Grafik für den JOYCE




Im „DMV-Sonderheft 2/87" wurde der folgende Artikel abgedruckt.
Ein gelungenes Grafik-Paket. Die Programmierung setzt auf der Hardware des JOYCE auf.



... Grafik mit Turbo Pascal und ohne GSX ...

So ziemlich für alle Rechner, auf denen Turbo Pascal läuft, gibt es grafikfähige Versionen dieser leistungsfähigen Programmiersprache — nur nicht für den JOYCE. Aber damit ist Schluß, denn jetzt gibt es eine leistungsfähige Grafikerweiterung, die sogar ohne die speicherplatzfressende GSX-Ein-bindung auskommt...

Am Anfang stand eine aus England stammende RSX, die unter Mallard Basic das Setzen und Löschen von Bildschirmpunkten erlaubte. Das Ganze war zwar etwas umständlich zu handhaben, aber immer noch besser als umständliches und speicherverschwendendes Operieren mit GSX, vor allem, wenn es nur um ein paar Linien ging. Mit der Zeit kam dann das Turbo Pascal-Fieber auf und die Idee einer Grafikerweiterung nahm Gestalt an. Was lag da näher, als auf Bekanntes zurückzugreifen. Allerdings war das RSX-Konzept nicht unbedingt das Wahre, hier mußte eine Abhilfe ersonnen werden, was schließlich zur Ersetzung der RSX durch External-Routinen führte. Dazu mußte natürlich die RSX erstmal »geknackt« werden — eine harte Nuß, die nach zwei durchhackten Nächten und einigen sehenswerten Systemabstürzen endlich zum ersten Erfolg führte: Pixel konnten schonmal gesetzt und gelöscht werden. Mit der Zeit wurde der maschinenabhängige Teil erweitert, erste Linien-Routinen geschrieben, Zeichensätze verändert und vieles mehr. »With a little help from our friends« — speziell Martin Schlöters Grafikserie »Vom Punkt zur 3.Dimension« aus »PASCAL International« verdanken wir viele Anregungen und »Zitate« — wuchs die JOYCE-Grafik-Erweiterung immer mehr, bald tummelten sich Kreise, Ellipsen und vieles mehr auf dem Schirm und der Drucker wurde mit einer Hardcopy-Routine zum Glühen gebracht. Schließlich war die vorliegende Turbo-Grafik fertig. Sie besteht aus einer Reihe von Include-Files, die, in den Programmtext eingebunden, ein völlig neues Turbo-Gefühl aufkommen lassen. Es wurde ein modularer Aufbau gewählt, der zwar zu mehr Files führte, aber ein selektives Einbinden der benötigten Funktionen erlaubt: nur das File KERNEL.INC muß eingebunden werden, der Rest nur je nach Bedarf. Im folgenden werden die einzelnen Funktionen der Erweiterung nach Include-Files geordnet vorgestellt. Auf umfangreichen theoretischen Ballast wird verzichtet, wissenschaftliche Hintergründe können vor allem in obiger Serie nachgelesen werden. Also ran an die Tastatur...

Als Arbeitsbereich wurde der Bildschirmbereich von 0/0 bis 719/247 (Grafik-Koordinaten) gewählt, was im Textmodus dem kompletten Bildschirm außer der Statuszeile (0/0 bis 89/30 in Textkoordinaten) entspricht. Dies hat zwei praktische Gründe: einerseits bleibt die Statuszeile frei für Meldungen, die nicht in die Bilder gehören, andererseits werden die Pixel der Statuszeile nicht gelöscht, wenn diese Statuszeile eingeschaltet ist. Eine Anpassung an den vollen Bereich des Bildschirms ist zwar möglich, dazu muß aber einiges in den Files geändert werden. Auch sollte Ihr Turbo Pascal an den großen Bildschirm des JOYCE angepaßt werden, da es sonst interessante »Nebeneffekte« geben könnte. Borland liefert Turbo Pascal aus unverständlichen Gründen in einer 80x24-Zeichen-Version aus, während der JOYCE ja 90x32 Zeichen unterstützt. Erreicht wird dies durch einen Durchlauf des Installationsprogramms TINST. Dort sollten die Fragen nach dem Senden von Terminal-Init- und TerminalExit-Sequenzen verneint und die neue Bildschirmgröße angegeben werden.


KERNEL.INC


KERNEL.INC ist das Herz unserer Grafik-Erweiterung und muß auf alle Fälle in die Programme eingebunden werden.
Es enthält neben dem unumgänglichen Maschinenspracheteil (auf den später noch eingegangen wird) die wichtigsten Elementarfunktionen und Teile, die auch von den anderen Include-Files benötigt werden. Die Funktionen im einzelnen:

GraphInit:
Diese Funktion ist die wichtigste der ganzen Erweiterung: sie initialisiert den MCode für die External-Routinen, und ohne die läuft die ganze Erweiterung nicht. Der Aufruf von GraphInit sollte daher der erste Befehl in Ihren Grafik-Programmen sein!!!

Plot(x,y,mode):
Der Plotbefehl ist (zusammen mit der External-Routine GX_Dot) der zweitwichtigste Teil der Erweiterung. Mit ihm ist es möglich, die einzelnen Punkte des Bildschirms (Pixel) anzusprechen. Dazu werden die Koordinaten des Punktes und der Zeichenmodus übergeben. Die Koordinaten sollten im Bereich 0<x<719 und 0<y<247 liegen (entspricht dem normalen Bildschirm ohne Statuszeile, Punkt 0/0 ist die linke obere Ecke), der Modus legt fest, ob das Pixel gesetzt (0), gelöscht (1) oder invertiert (2) werden soll, bei Modus 3 wird geprüft, ob ein Pixel gesetzt oder gelöscht ist (wird in der Funktion DotColor verwendet und ist normalerweise uninteressant).

Screen_Off, Screen_On:
Über den Port 248 kann der Bildschirm ein- und ausgeschaltet werden. Dies ist besonders praktisch, wenn Bilder »versteckt« gezeichnet werden sollen. (Man sollte aber nicht vergessen, den Bildschirm vor dem Verlassen des Programmes wieder einzuschalten...)

HideCursor, ShowCursor:
Falls der Cursorblock stören sollte, kann er mit diesen Befehlen ein- und ausgeschaltet werden. Erreicht wird dies ganz einfach durch die Ausgabe der entsprechenden Escape-Sequenzen.

DotColor(x,y):boolean:
Mit dieser Funktion kann der Zustand eines Pixels abgefragt werden, sie liefert den Wert TRUE, wenn das Pixel gesetzt ist. (Wird z.B. in der Hardcopy-Prozedur benötigt.)

Symbol(Code,rp0,..,rp7):
Diese Prozedur ermöglicht das Ändern der Bildschirmmatrix eines Zeichens, indem der ASCII-Code des Zeichens und das neue Muster als 8 Bildzeilen zu 8 Zeichen übergeben werden. Dabei bedeutet '*', daß der entsprechende atrixpunkt gesetzt wird, ein Leerzeichen, daß er dunkel bleibt.

Symbol(255,'********',
           '*      *',
           '*      *',
           '*      *',
           '*      *',
           '*      *',
           '*      *,
           '********')
         
ändert also die Darstellung des Zeichens #255 in die angegebene Form. Diese Routine wurde samt der zugehörigen Umwandlungsroutine GX_Convert (wandelt die Binärzeile in einen Bytewert um) mit freundlicher Genehmigung der Autoren aus der CGX-Grafikerweiterung für den PC 1512 übernommen.

Hex_Symbol(Code,r0,..,r7):
Funktioniert genauso wie Symbol, allerdings werden die Werte direkt als Byte-Werte übergeben. Beide Prozeduren verwenden die External-Routine GX_Symb, die eine Zeichenmatrix in das Matrix-RAM kopiert. Zu beachten ist noch, daß die Compilerendadresse niemals größer als $F3FF gesetzt wird, da sonst die External-Routinen von Variablen überschrieben werden, aus ähnlichem Grund muß auch der Run-Modus vermieden werden, wenn man nicht einen klassischen Systemabsturz erleben will. (Die Standard-Endadresse ist sowieso kleiner, man braucht im Prinzip also nichts verändern.)

 


SIMPLE.INC


Dieses Include-File stammt eigentlich noch aus der Anfangsphase der Grafikerweiterung und enthält sehr einfache Grafikbefehle. Wesentlich leistungsfähigere Versionen finden sich in GRAPHLIB.INC, auf Grund ihrer etwas anderen Syntax und dadurch für manche Anwendungen vielleicht besser geeignet, seien sie hier vorgestellt:

S_Horizontal(x1,x2,y,mode):
Zeichnet eine horizontale Linie von x1=y nach x2=y im durch mode spezifizierten Plotmodus.

S_Vertikal(x,y1,y2,mode):
Zeichnet eine vertikale Linie von x/y1 nach x/y2 im durch mode spezifizierten Plotmodus.

S_Box(x,y,xlen,ylen,mode):
Zeichnet einen Kasten im Plotmodus mode ab der Koordinate x/y mit den Maßen xlen in X- und ylen in Y-Richtung.

 


GRAPHLIB.INC
- Die Grafikbibliothek -


Mancher von Ihnen wird sich vielleicht beim Lesen gesagt haben: »Jetzt kann ich also Punkte an beliebige Bildschirmpositionen setzen, sie löschen, invertieren, ihren Status abfragen... Was soll's, damit habe ich noch lange keine Grafik!!!« Richtig, aber die kommt jetzt; Die Prozeduren in GRAPHLIB.INC sind zumindest zum Teil an GSX orientiert. Sie bieten vieles, was der Bildschirmtreiber DDSCREEN.PRL ebenfalls kann; manchmal etwas weniger, manchmal etwas langsamer, aber oft vielseitigere und vor allem variablere Funktionen und — ohne den Rattenschwanz an Funktionen, die man für das Programm, was man gerade schreibt, sowieso nicht braucht, die aber Speicherplatz »fressen«, den man wiederum oft sehr nötig hat. Aus GRAPHLIB.INC kann man sich die entsprechenden Teile wenn nötig einzeln in den Quelltext kopieren.


Die Prozeduren und ihre Verwendung


Um eine Linie, einen Kreis oder andere Objekte auf den Bildschirm zu zaubern, müssen zunächst alle Punkte berechnet und einer nach dem anderen gesetzt werden. Dafür sind die Prozeduren LINE() bis CIRCLE() zuständig. LINE() zieht eine Linie zwischen den Bildschirmpunkten, deren Koordinaten im Aufruf übergeben wurden. Die einfachste Art dies zu tun, wäre, mit Hilfe der Geradengleichung f(x) = Steigung * x + y-Achsenabschnitt für die xKoordinaten die Werte für f(x) zu berechnen, sie zu Runden, da der Bildschirm ja nur diskrete Schritte erlaubt, und sie anschließend mit PLOT() zu setzen. Da die Berechnung über REAL-Werte erfolgen müßte, wäre dies aber mit Sicherheit auch die langsamste Art. LINE() rechnet nur mit INTEGER-Variablen. Ausgangspunkt ist auch hier wieder die Geradengleichung — diesmal aber ohne Achsenabschnitt. Vielleicht erinnern Sie sich noch mehr oder weniger dunkel an den Mathematikunterricht?! Die Steigung einer Geraden läßt sich aus den Differenzen der Koordinaten zweier Punkte — in unserem Fall von Start und Endpunkt — berechnen. Umgeformt lautet die Gleichung dann: x * DY = y * DX. Mit DX und DY werden bei jedem Schritt die Abweichungen der gesetzten Punkte von der vorgegebenen Gerade bestimmt und zur Auswahl der nächsten Schrittrichtung benutzt. Mehr Details will ich Ihnen und mir ersparen. BOX() bringt ein Rechteck auf den Bildschirm. Übergeben werden die Ecken links oben und rechts unten und — wie auch bei den anderen Prozeduren — der Modus (setzen, löschen oder invertieren). Um die Box nicht unnötig zu bremsen, wird nicht LINE() zum ziehen der Linien benutzt, sondern die Sonderfälle für horizontale und vertikale Linien.

POINT_SWAP() sorgt dafür, daß die Startkoordinate immer kleiner als die Endkoordinate ist und nicht über den Rand gemalt wird. SQUARE() ist ein Spezialfall von BOX() und zeichnet — wie zu erwarten — ein Quadrat. Als Parameter werden die linke obere Ecke und die Breite in Pixeln übergeben. Wie wird nun das Quadrat zum Quadrat? Hierfür ist die Konstante ASPECT_RATIO zuständig; sie gibt das Verhältnis von Pixelhöhe zu Pixelbreite an. Ihr Wert kann durch Ausmessen von »Boxen« am Bildschirm ermittelt werden — probieren geht auch hier über studieren. Auch ELLIPSE() und CIRCLE() erhalten durch das Einbeziehen der ASPECT_RATIO erst das gewünschte Aussehen. Ebenso wie die Prozedur LINE() vermeidet auch ELLIPSE() weitgehend REALzahlen. Auch hier wird nur die Abweichung betrachtet, die durch jeden Schritt entsteht. Außerdem macht sich die Symmetrie der Figur nutzbringend bemerkbar: Wir müssen nur ein Achtel aller Punkte berechnen, alle ändern erhalten wir durch Spiegelungen entsprechende Kombination von Addition und Subtraktion der errechneten Werte von den Koordinaten des Mittelpunktes. Radius_x gibt die Anzahl der Pixel der x-Halbachse an, die y-Halbachse wird so umgerechnet, daß das Größenverhältnis auf dem Bild dem gewünschten Verhältnis von Radius_y zu Radius_x entspricht. CIRCLE() wird als Ellipse mit gleich langen Halbachsen berechnet; übergeben wird dementsprechend außer den Mittelpunktskoordinaten nur noch der Radius.

Soweit die »Grundfunktionen«. Aber es gibt noch mehr; Die Prozedur PLOT_MARKER() ist vor allem zur Darstellung von Meßwerten u.a. gedacht. Sie setzt auf den Punkt x,y einen »Marker« aus den in MARKER_TYPE deklarierten Elementen. PLOT_MARKER(10,20,Kreis,0) zieht also einen Kreis um den Punkt 10,20. Wenn Sie MARKER_HEIGHT mit im Aufruf übergeben, können Sie auch verschiedene Größen erhalten, was mir persönlich allerdings nicht besonders sinnvoll erschien, da die Marker dann zum Teil doch etwas unförmig werden. Als nächstes folgen vier POLY_...-Prozeduren. Wie der Name vermuten läßt, wird hier etwas mehrfach ausgeführt. Die erforderlichen Koordinaten werden als zweidimensionales Array übergeben; POINT_ARRAY(.i,0.) enthält die x-, POINT_ARRAY(.i,1.) die y-Werte. POINT_ARRAY ist auf 250 dimensioniert, was für die meisten Anwendungen völlig ausreichen dürfte. Die Zahl der wirklich benutzten Arrayelemente wird als Parameter mit übergeben. POLY_PLOT() setzt lediglich Punkte auf die Koordinatenpaare des Arrays; POLY_MARKER() die in MARKER_TYPE definierten Marker. POLY_LINE() verbindet die Punkte in der Reihenfolge, in der sie im Array enthalten sind, mit Linien. Alle Prozeduren können vielseitig eingesetzt werden. Etwa um Funktionen oder Meßwerte darzustellen, wie im Beispiel GRAPHIC.PRO demonstriert, oder um Polygone zu zeichnen. Bei POLY_LINE() muß dann das erste Koordinatenpaar noch einmal als letztes im POINT_ARRAY enthalten sein, damit eine geschlossene Figur entsteht. Ebenso verhält es sich bei der vierten POLY_..-Prozedur POLY_FILL(). Sie füllt ein Polygon, dessen Eckpunkte als POINT_ARRAY übergeben wurden, im entsprechenden Modus, d.h. sie füllt den Inhalt »weiß«. löscht oder invertiert alle Punkte.

Allerdings wird es durch die Art der Berechnung notwendig, im Anschluß an das Füllen mit PLOY_LINE() noch die 'Begrenzung' zu zeichnen. Ihre Anwendung im Demo-Programm DREID (entnommen aus PASCAL INTERNATIONAL 2(2), Januar 1987) zeigt am besten den Effekt, den man so erzielen kann: Hidden-LineDarstellungen ohne komplizierte Umrechnungen und große Arrays. Soweit zum Inhalt von GRAPHLIB.INC.

 


PATTERNS.INC
Erweiterungen für LINE() und POLY_FILL()


Das Modul PATTERNS.INC bietet neben PATTERN_LINE(), einer erweiterten LINE()-Prozedur, eine analoge Erweiterung von POLY_FILL(), PATTERN_FILL(). Wo in der einfachen Version nur der Modus angegeben werden konnte, werden jetzt die Muster LINE_TYPE und FILL_TYPE übergeben: fünf Linienarten und mindestens neun Füllmuster sind in den beiden Prozeduren verfügbar. Wem dies nicht ausreicht oder wem das Vorhandene nicht gefällt, der kann sich seine eigenen Varianten definieren - als * und Leerzeichen in einem String, einfacher geht's wirklich nicht. Um die Füllmuster zu erhalten, werden die Zeichen 248 bis 255 des Bildschirmzeichensatzes benutzt. Zwar gehen diese dabei für den Gebrauch innerhalb des Programms verloren, aber diese Vorgehensweise hat zwei Vorteile, die dies rechtfertigen. Der erste ist, daß auf diese Weise auch die »normalen« Zeichen als Füllmuster verwendet werden können; z.B. das Leerzeichen (# 32) oder die Zeichen zwischen 128 und 159, die die Rahmen vieler JOYCE-Programme aufbauen. Im Demoprogramm ist die einfache, senkrechte Linie als Beispiel aufgenommen worden. Der zweite Vorteil ist, daß man großflächige »Füllungen« auch mit write(chr(# #)) vornehmen kann, wenn die Felder sich an die Zeilen und Spalten des Textbildschirms halten, was um einiges schneller ist, als der Weg über die Grafik.

 


GRAPHIC.PRO
Anregungen für eigene Erweiterungen


Zum Abschluß noch einige Worte über die »Programmgestaltung«. Für viele Anwendungen ist es sinnvoller, wenn man im »eigenen Koordinatensystem« arbeiten kann, ohne vorher alle Daten in Systemkoordinaten umrechnen zu müssen. GRAPHIC.PRO stellt als Beispiel eine Prozedur vor, mit der man an beliebige Bildschirmausschnitte, die durch die VIEW_...- Parameter festgelegt werden, ein Koordinatensystem zeichnen kann, in dem ein POINT_ARRAY dargestellt wird. Die Koordinaten der Achsen können als WIN_...-Parameter angegeben werden. Zur Umrechnung der Benutzerkoordinaten in die Systemkoordinaten dient die Prozedur KOORD_TRANS(). Wenn das ganze Programm in Benutzerkoordinaten arbeiten soll, kann man VIEW_X_MIN, VIEW_X_MAX, usw. als globale Variablen deklarieren und beispielsweise über eine Prozedur SET_VIEWPORT(), ähnlich wie CBASIC sie zur Verfügung stellt, verändern. Weiterhin kann man dann in der PLOT()-Prozedur abfragen, ob diese Grenzen überschritten werden, und nur in solchen Fällen die Punkte setzen, in denen sie innerhalb dieser Grenzen liegen. Weist man zusätzlich jeweils die aktuelle Position des 'Grafikcursors' zwei globalen Variablen - C_X_POS und C_Y_POS zu, so ist der Weg offen zur eigenen Turtlegrafik a la LOGO mit Prozeduren wie DRAW_TO usw. oder zur Abfrage der Cursorposition und damit zum Beispiel zu Menueauswahlen wie sie in DR DRAW verwendet werden.

 


PRINTAT.INC


PRINTAT.INC enthält einen wesentlich erweiterten Ausgabebefehl für Turbo Pascal. Mit ihm ist es möglich, eine Positionierung der Ausgabe mit verschiedenen Schriftarten sowie verschiedenen Ausgaberichtungen zu verbinden. Die Syntax des neuen Printbefehls ist PRINTAT(x,y,font,heading,text). X und y sind die Koordinaten (bezogen auf Zeichen-Koordinaten, 0<x<90, 0<y<32) für den Beginn der Textausgabe und entsprechen denen des Turbo-Standards »gotoxy()«. Font spezifiziert eine von 5 verschiedenen Schriftarten. Im einzelnen sind 5 Schriftarten möglich:

Font=0: normaler Zeichensatz
Font=1: Schmalschrift
Font=2: Fettschrift
Font=3: inverse Schrift (entspricht dem Turbo-Befehl »Lowvideo«)
Font=4: Kursivschrift

(Zur Erzeugung dieser Schriftarten vgl. Serie »Vom Punkt zur 3. Dimension«, Pascal International 8/87 S.34 ff.)

Heading bestimmt die Ausgaberichtung des Textes. Es sind hierbei vier Richtungen möglich, die den Text um jeweils 90 Grad gedreht ausgeben. (Heading 0 = normale Ausgabe, vgl. PTEST.PAS). Der Text kann maximal 90 Zeichen umfassen (Typ Strg_90, definiert in KERNEL.INC). Er wird Zeichen für Zeichen ausgeben, wobei die Zeichenmatrix für jedes Zeichen aus dem Matrix-RAM ausgelesen wird (GX_Get), je nach Bedarf gedreht und anschließend als Zeichen mit dem ASCII-Wert 0 in die Matrix zurückgeschrieben und normal ausgedruckt wird. Die Matrix für dieses Zeichen ist also geändert, Sie sollten in Ihren Programmen den Befehl »write #27,#0« vermeiden. (Oder das entsprechende Sonderzeichen bei Bedarf neu definieren...) Eine Demonstration des neuen Ausgabebefehls finden Sie in PTEST.PAS.

 


SPRINTAT.INC


Dieses Include-File verdankt seine Entstehung eigentlich einem Tippfehler bei der Entwicklung von PRINTAT.INC. Es stellt den Befehl SPRINTAT zur Verfügung, der von Syntax und Optionen genau PRINTAT entspricht, nur daß hier die Ausgabe in Spiegelschrift erfolgt...

 


HARDCOPY.INC


Grundlage dieser Hardcopy-Routine war ein Listing in PASCAL International, welches jedoch zuerst funktionsfähig gemacht und anschließend erweitert wurde.

Mit ihr ist es möglich, einen beliebigen Bildschirmbereich in 4 Größen horizontal oder vertikal auszudrucken. Die Syntax ist Hardcopy(left,top,right,bottom,size,direction). Dabei sind »left« und »top« die Koordinaten des linken oberen, »right« und »bottom« des rechten unteren Pixels, die den Ausgabebereich festlegen. »Size« legt den Vergrößerungsfaktor fest und muß 1,2,4 oder 8 betragen. »Direction« gibt die Ausgaberichtung (»V« oder »H«) an.

Zu beachten ist, daß diese Optionen gewissen Einschränkungen unterliegen. Da der JOYCE-Drucker nur 960 Punkte in einer Zeile drucken kann, ist es z.B. nicht möglich, eine Hardcopy des ganzen Bildschirms horizontal in doppelter Größe auszudrucken, weil dazu eine Auflösung von 1440 Punkten nötig wäre. Man sollte also schon vor dem Aufruf etwas rechnen. Ist eine Ausgabe wegen falscher Parameter nicht möglich, bricht die Routine von allein ab. In vertikaler Richtung sind keine Grenzen gesetzt, allerdings kommt es in diesem Modus zu Verzerrungen der Proportionen.

 


DISKETTE.INC


Natürlich möchte man die Grafiken nicht nur auf Papier, sondern zur späteren Verwendung eventuell auch auf Diskette speichern. Hierzu dient das Include-File DISKETTE.INC. Es stellt die Prozeduren SaveScreen (Dateiname) und LoadScreen(Dateiname) zur Verfügung. Als Parameter wird der Dateiname über den vordefinierten Typ Strg_14 übergeben, wodurch neben Namen und Extension auch ein Laufwerk angegeben werden kann. Diese Funktionen übertragen den Bildschirminhalt auf Diskette oder umgekehrt und haben nur einen kleinen Nachteil: sie benötigen einen 22 KByte großen Puffer, der natürlich vom Hauptspeicher abgeht (desgleichen auf der Diskette...). Dafür sind sie allerdings sehr schnell: da der Bildschirm nicht Pixel für Pixel sondern zeichenweise abgetastet wird, ist der Vorgang ca. 64 mal so schnell wie ein Vorgehen mit DotColor und Plot (Diskettenzugriffe vernachlässigt). Der Bidaufbau erfolgt nach dem Einlesen etwa genau so schnell wie eine Ausgabe mit dem write-Befehl. (Evtl. kann man auch mit Screen_Off einen versteckten Bildaufbau erreichen.) Anzumerken ist noch, daß keine Fehlerprüfung über IORESULT erfolgt ( - ein Zeichen des Vertrauens in die Anwender...).

 


FONT.INC


Ähnlich wie mit den Bildern verhält es sich mit den Zeichensätzen. Schön, wenn man sie auch auf Diskette hat. Die in diesem File enthaltenen Prozeduren LoadFont(Dateiname) und SaveFont(Dateiname) ermöglichen das Laden und Speichern von kompletten Zeichensätzen. Die Zeichensätze müßen als 2 KByte großes File vorliegen (dies ist auch die benötigte Puffer-größe). Die *.LET-Files des »Mouse Packs« können direkt verwendet werden, bei mit dem »Character Designer« erstellten Zeichensätzen muß erst der Ladervorspann mit LETCOM entfernt werden.

 


SOUND.INC


In Sachen Musik ist auf dem JOYCE ja relativ wenig los, CD-Qualtät kann der eingebaute Beeper beim besten Willen nicht liefern. Etwas mehr als das kurze Piepsen bei der Ausgabe von »^G« ist aber dennoch möglich, wenn man den Beeper direkt ansteuert. Zuständig hierfür ist unser Universal-port 248, über den man den Beeper beliebig ein- und ausschalten kann. SOUND.INC stellt hierzu folgende Funktionen zur Verfügung:

Sound_On:
Schaltet den Beeper für eine beliebig lange Zeit ein.

Sound_Off:
Schaltet den Beeper wieder aus.

Play(Anzahl,Einzeit,Auszeit):
Startet einen Beeper-Zyklus, der Anzahlmal durchlaufen wird, wobei zwischen den Ein- und Ausschalten des Beepers die entsprechende übergebene Zeit vergeht. In der vorliegenden Version wird diese Zeit noch durch eine Leerschleife erzeugt, durch Verwendung des Turbo-Befehls Delay() ließe sich hier eventuell eine »Normierung« erreichen. Musikalische Ehren kann man damit zwar nicht verdienen, einige gute bzw. abwechlungsreiche Effekte sind aber dennoch möglich. Zu erwähnen ist noch, daß SOUND.INC das einzige Include-File dieser Reihe ist, welches ohne KERNEL.INC auskommt...

 


Technisches


Das Listing GRAFINC.PRN [hier als Z80-Quelldatei] zeigt den Assemblercode der External-Routinen GX_Plot, GX_Symb GX_Get und GX_ScrAcc. Sie machen alle vier von der XBIOS-Funktion #35 (Einblenden des Screenenvironments) Gebrauch und leisten folgendes:

GX_Plot:
Berechnet und bearbeitet Pixel werte über das Roller-RAM. Lage im Speicher ab $F400, per absolute Variablen übergebene Parameter sind X-Koordinate ($F410/11), YKoordinate ($F412) und Plotmodus ($F413). Optionaler Einsprung (z.B. für Inline-Routinen) bei $F407 mit X im DE-Register, Y und Modus in HL. Bei der Statusabfrage (Modus 3) wird der Zustand in die Speicherstelle des Modus zurückgeschrieben (Wert<>0 = Pixel gesetzt).

GX_Symb:
Kopiert 8 Bytes aus einer Tabelle ab $F477 in das Matrix-RAM. Die Zieladresse muß aus dem Zeichencode errechnet und als absolute Variable bei $F472/73 übergeben werden. Einsprung nach Übergabe der Werte bei $F462, kein optionaler Einsprung möglich.

GX_Get:
Kopiert 8 Bytes aus dem Matrix-RAM in die Tabelle ab $F477. Die Quelladresse muß aus dem Zeichencode berechnet und als absolute Variable bei $F489/99 übergeben werden. Einsprung nach Übergabe der Werte bei $F47F, kein optionaler Einsprung möglich.

GX_ScrAcc:
Kopiert 8 Byte, die einem Standard-Zeichen entsprechen, aus dem VideoRAM in die Tabelle ab $F477 oder umgekehrt. Die Koordinaten werden als Text-Koordinaten absolut übergeben: 0<x<89 bei $F4AO, 0<y<30 bei $F49E. In $F4B9 wird die Zugriffsrichtung übergeben: steht hier 0, wird vom Video-RAM in die Matrix geschrieben, andernfalls wird die Matrix in den Bildschirm kopiert. Diese Routine wird zur Zeit nur im File DISKETTE.INC verwendet, andere Möglichkeiten wären eine Verwendung in PRINTAT.INC oder zur Darstellung von Windows und Sprites (bereits in Planung...). Der Einsprung erfolgt nach Übergabe der Werte X, Y und AccessMode (ggf. auch der Matrix) bei $F494.

Mit diesen Informationen ist es möglich, die External-Routinen auch direkt anzusprechen. Dies dürfte besonders für versiertere Programmierer interessant sein, da sich durch die Verwendung von Inline-Code noch eine wesentliche Steigerang der Geschwindigkeit erreichen ließe. Anregungen und Verbesserungsvorschläge aus der Leserschaft sind jederzeit willkommen...

 


Demo-Programme


Zu dieser Grafikerweiterang existieren einige Demos (teilweise noch aus der Entwicklungsphase), die hier jedoch nicht alle abgedruckt werden können. Auf der DATABOX zum Sonderheft sind sie jedoch komplett als Quelltexte enthalten.
Es sind im einzelnen:
DEMO1.*: Verwendung von Elementarbefehlen
DEMO.*: komplexere Dinge
PTEST.*: Möglichkeiten des PRINTAT-Befehls

Ein besonderes 'Zuckerl' ist das Programm DREID.*. Es stellt Funktionen als dreidimensionale Netz-Grafiken dar und wurde in PASCAL International 2/87 für den ATARI ST veröffentlicht. Hierzu steht ein eigenes Include-File namens DREID.INC für die Grafikroutinen zur Verfügung. Das Programm läuft jetzt auch auf dem JOYCE und ist nur rund 10 mal langsamer, was angesichts der Tatsache, daß es sich um reines Turbo Pascal handelt, recht beachtlich ist. Es sind 3 Hardcopy-Arten möglich, die nach dem Bildaufbau über <FORM> (=normal), <TAB> (=doppelt hoch) und <EXIT> ( = fett + doppelt hoch) ausgewählt werden. <RETURN> ermöglicht die Eingabe von neuen Winkeln, wird für Beta 0 eingegeben, so endet das Programm.

 


Ausblick


Es dürfte klar sein, daß die vorliegende Version der Grafik-Erweiterung noch nicht unbedingt der Weisheit letzter Schluß ist, aber für den Anfang ist sie bestimmt brauchbar. Daher also viel Vergnügen mit dem neuen Turbo Pascal. Neue Teile dürften bald folgen, wir sind auch auf die Resonanz bei der Leserschaft gespannt. Also bitte keine Zurückhaltung in Sachen Anregungen, Verbesserangen und Anwendungen... (Besonders interessieren würde uns ein Tip, wie man etwas mehr Farbe auf den JOYCE bekommt, denn das ist uns beim besten Willen nicht gelungen...) Was im Augenblick noch in unseren Köpfen heramspukt, wären Erweiterungen in Richtung Sprites und Windows mit Wiederherstellung des Bildschirms sowie eine generelle Geschwindigkeitssteigerang und eine Möglichkeit zur Verwendung mit dem »Mouse Pack« erstellter Bilder. Für diese Sonderheft soll es jedoch genug an Grafik sein, wir wünschen »Auf Wiederlesen« im nächsten Sonderheft oder im Stamm-Magazin...

M. Anton / E. Wirth
© DMV-Verlag

LITERATUR
Martin Walser, Andreas Stiller,
Plotter selbstgebaut, Teil 3:
Treiber Magazin für Computer Technik,
November 1984, S. 56 - 59

Frank Schmidt,
Grafik mit dem Drucker,
Erstellung und Ausgabe hochauflösender Grafik im Bitmustermodus Magazin für Computer Technik, Juni 1984, S. 44 - 48

Roland Waclawek,
Kreisgenerator, »Ganz schnelle« Kreise in Theorie und Z80-Praxis Magazin für ComputerTechnik,
September 1986, S. 122 - 126

Martin Schlöter,
Vom Punkt zur dritten Dimension (Serie;)
PASCAL INTERNATIONAL ab Ausgabe 2(4),
Januar 1987

Ron Worston, Armstrad PCW 8256 Plot RSX Personal Computer World 9(7), July 1986, pp. 190 - 192

 


Bearbeitet von  Werner Cirsovius