Bei einem tieferen Blick mit einem Monitor in das neue OMIKRON.BASIC 3.00 kam es an den TAG: OMIKRON.BASIC kann mehr als im Handbuch angegeben. Was lag also näher, als diesen undokumentierten Befehlen auf den Grund zu gehen?
Die Rücksprache mit der Herstellerfirma ergab, daß diese Befehle zwar eingebaut aber bislang zurückgehalten wurden, da sie noch nicht 100%ig ausgetestet waren, und OMIKRON.Software dem Kunden nur fehlerfreie Befehle präsentieren will.
Um die Spannung nicht allzu groß zu machen - Überraschungen wird es in diesen Monat eh noch genug geben -, beginne ich am besten gleich mit dem ersten Befehl.
NDC [<X>,<Y>,<W>,<H>]
NDC [<X>,<Y> TO <W>,<H>]
NDC bewirkt die interne Umrechnung von Grafikbefehlen (z.B. BOX, CIRCLE,..) auf normalisierte Koordinaten (0..32767).
Mit Hilfe dieses Befehls können Programme, die Graphik ausgeben, im Programm mit festen Werten arbeiten und trotzdem auf allen Monitortypen lesbare Ausgaben erzielen. Dazu ist es nur am Programmanfang nötig, die absolute Auflösung zu erfragen, und mit NDC die Umrechnungskoordinaten zu setzen.
Beispiel:
' NDC
' s/w und Farbe
Maxint%=32767
XBIOS (Res,4)' Auflösung holen
Xmax=639+320*(Res=0)' maximale Koordinaten
Ymax=399+200*(Res<2)' errechnen
NDC 0,0,Xmax,Ymax'NDC einschalten
CLIP 0,0,maxint%,maxint%
'
DRAW 0,0 TO Maxint%,Maxint%
DRAW 0,Mqxint% TO Maxint%,0
Es erscheinen die zwei Diagonalen auf dem Bildschirm, und zwar in jeder Auflösung. NDC ohne Parameter macht die Einstellung wieder rückgängig und kehrt zum normalen Koordinatensystem zurück.
Es folgt ein etwas komplexeres Beispiel des NDC-Befehls, wo zunächst die Auflösung erfragt und daraus die maximalen X-und Y- Koordinaten errechnet werden.
Anschließend berechnet das Programm eine Sinus-Welle und legt die Werte in einem Feld ab. Dieses wird sodann mehrfach geplottet, aber immer mit unterschiedlichem NDC-Befehl. Es zeigt, daß es mit NDC eine Leichtigkeit ist, Programme so zu schreiben, daß sie in jeder Auflösung lauffähig sind.
Falls sie schon einmal einen Blick in einschlägige GEM-Literatur geworfen haben, werden Sie von NDC (Normalized Device Koordinates) schon gehört haben, doch im GEM waren sie bislang nicht funktionsfähig - OMIKRON.-BASIC macht’s möglich. Im übrigen ist die gesamte GEM-LIB ‘NDC’-fähig.
Es gibt aber noch eine andere Möglichkeit, Programme für alle Auflösungen zu schreiben. Im vorigen Beispiel wurden nur die normalen ST-Auflösungen berücksichtigt - da gibt es nun aber beispielsweise den Matrix-Screen, der wesentlich mehr Punkte auflösen kann. Damit Ihre neuen Programme auch in Zukunft auf allen Monitoren laufen, holt man sich die maximalen Koordinaten per Wind_Get. Praktisch hierbei ist, daß die Menüleiste gleich ausgeschlossen wird. Probieren Sie das folgende Beispiel einfach einmal aus (siehe unter "NDC" auch für den Großbildschirm).
' NDC
' s/w und Farbe Maxint/o=32767 #
XBIOS (Res,4)' Auflösung holen
Xmax=639+320*(Res=0)' maximale Koordinaten
Ymax=399+200*(Res<2)' errechnen
Xy!=Ymax/Xmax' Faktor zwischen x und y
DIM X(Xmax),Y(Xmax)
FOR I=0 TO Xmax' Funktionswerte errechnen
X(I)=I*Maxint%/(Xmax)
Y(I)=Maxint%/2+ SIN(I/Ymax* 10)*Maxint%/2
NEXT I
FOR X=0 TO Xmax/2-1 STEP 10
CLS
Y=X *Xy!:B=Xmax-2*X: H=B*Xy!
NDC X,Y,B,H' <-----neues Koordinatensystem
CLIP 0,0,maxint%,maxint%
BOX 0,0 TO Maxint%,Maxint%' Rahmen ziehen
FOR I=0 TO Xmax
DRAW X(I),Y(I)' Funktion zeichnen
NEXT I
NEXT X
' NDC auch für Großbildschirm
'
LIBRARY Gem ,"f:\omikron\gem.lib'" GEMLIB laden
Maxint%=32767
Appl_Init ’ Rein ins GEM
Wind_Get(0,4,X,Y,B,H)' Maximale Ausmaße holen
NDC X,Y,B,H ' NDC-Koordinaten
CLIP 0,0,Maxint%,Maxint% ' Clip mal wieder
PRINT : PRINT X,Y,B,H ' Werte mal ausgeben
DRAW 0,0 TO Maxint%,Maxinf% ' Diagonalen
DRAW 0,Maxint% TO Maxint%,0 ' zeichnen
WAIT 10 ' Kurze Pause
Appl_Exit' Raus aus GEM
LIBRARY CODE Gem
Diese Befehle sind bekannt aus dem VDI, doch ist es allemal bequemer, sie direkt im BASIC aufrufen zu können.
POLYGON und PPOLYGON dienen zum Zeichnen von Linienketten, wobei PPOLYGON diese Fläche nach einem bestimmten Schema füllt.
Zwar kann man mit mehreren DRAW-Anweisungen diesen Befehl emulieren, doch spätestens beim Versuch, ausgefüllte Flächen in einer akzeptablen Zeit auf den Bildschirm zu zaubern, dürften die meisten Programmierer Ihre Schwierigkeiten haben.
Die Eckdaten des Polygons werden zu diesem Zweck in ein zweidimensionales Integer-Feld abgelegt, dessen erster Index zweidimensional ist, der zweite der Anzahl der Eckpunkte entspricht.
Ein beispielhafter Aufruf [P]-POLYGON A%(0,8) zeichnet ein nicht unbedingt geschlossenes Vieleck - den abgelegten Koordinaten von A%(0,0) bis A%(1,8) entsprechend, wobei in A%(0,) die X-Koordinaten und in A%(1,) die Y-Koordinaten verlangt werden.
entscheidet, ob ein Grafikobjekt (z.B. PCIRCLE, PBOX,..) umrahmt oder rahmenlos gezeichnet wird.
OUTLINE OFF - ohne Rahmen
OUTLINE ON - mit Rahmen
Zwar existiert dieser äußerst leistungsstarke Befehl schon immer, doch hat er einige Features hinzubekommen.
Neu ist die Berücksichtigung von Clippingrechtecken und die mögliche Verknüpfung von Speicherbereichen, wenn das Ziel der Speicher ist, also nicht nur beim Kopieren vom Speicher in den Bildschirmbereich. Sollte ein Blitter installiert sein, wird dieser angesprochen, falls nicht, wird nicht die BITBLT-Routine des Betriebssystem angesprungen, sondern die eigene, wesentlich schnellere Routine des Interpreters.
Die Syntax lautet wie bisher:
BITBLT <X>,<Y>,<W>,<H> TO <MEMORY> ; <MODUS>
Damit man auch, ohne den Tastaturprozessor in Eigenregie quälen zu müssen, die Joystickstellung erfragen kann, wurde eine neue Funktion implementiert.
JOYSTICK(<Nummer>)
Nummer steht für die Nummer des Joystickports, wobei 0 für den Maus-, 1 für den Joystickport steht. Bit 7 des Rückgabewertes gibt den Status des Feuerknopfes, Bit 0-3 die Richtung an. Um die Abfrage zu aktivieren, muß dem Tastaturprozessor mitgeteilt werden, daß er ab sofort Joystickdaten senden soll. Das Beispielprogramm verdeutlicht die Abfrage:
Nach der Abfrage muß der Tastaturprozessor wieder auf Normalmodus geschaltet werden, da sonst die Maus inaktiv bleibt (siehe letzte Programmzeile).
Sie erhalten folgende Werte:
5 1 9
4 128 8
6 2 10
' JOYSTICK
BIOS (,3,4,201' Abfrage ein
REPEAT
PRINT JOYSTICK(1),
PRINT JOYSTICK(0)' Bitte Maus raus !!!
UNTIL INKEY$ <>""' bis Tastendruck
BIOS (,3,4,8)' Abfrage aus
Zum Einbinden kurzer Maschinenroutinen steht nun der INLINE-Befehl zur Verfügung. Der Maschinencode wird in einem einfachen String angegeben. Die Länge ist dabei allerdings auf 124 Byte begrenzt.
INLINE hat den großen Vorteil. daß der Befehl selbst alle Register rettet (auch der RTS am Ende kann entfallen). Das INLINE-Programm kann mit ihnen also sorglos umgehen -der Stack-Pointer allerdings sollte wieder korrigiert werden.
Das folgende Beispiel beinhaltet einen INLINE-Aufruf, der den gesamten Bildschirminhalt achtmal um ein Pixel nach oben schiebt. Man erhält somit einen wunderbaren Softscroll, (Das Beispiel für den INLINE-Aufruf ist auf der nächsten Seite zu sehen).
In der Dateibehandlung hat sich auch einiges getan. GEM-DOS-Programmierer werden mit den neuen Befehlen wenig Schwierigkeiten haben, denn sie sind in der Funktion mit den entsprechenden GEMDOS-Aufrufen identisch, nur sind sie in BASIC-Syntax eben leichter anzuwenden. Im folgenden soll die Syntax gezeigt werden, die genauen Funktionsweisen müssen Sie bei den GEMDOS-Funktionen nachschlagen (z.B. im OMIKRON.Handbuch).
OPEN "U",<Filenr>:<Filename>
eröffnet eine Datei für folgende Befehle
SEEK<Filenr>,<Pos>[,Mode>]
setzt den Dateizeiger auf die angegebene Position
GET <Filenr>,<Addr>,<Len>
holt Len-Bytes aus Datei und speichert im Speicher ab Adresse Addr
GET <Filenr>,<String>,<Len>
liest in String z.B. GET 1,-AS.100
PUT <Filenr>,<Addr>,<Len> bzw.
PUT <Filenr>,<String>
schreibt in die Datei z.B. PUT 1 ,MID$(A$,3,97)
Die Bedeutung der Variablen Pos ist wie folgt:
Pos=0: Position wird vom Dateianfang gezählt (entspricht Aufruf ohne Mode)
Beispiel:
' POLYGON PPOLYGON
' Beispiel s/w und Farbe
XBIOS (Res,4)' Auflösung erfragen,
Xmax=639+320*(Res=0)' maximale Koordinaten
Ymax=399+200*(Res<2)' errechnen
CLIP 0,0 TO xmax.ymax
N=10’ Anzahl der Polygon-Ecken
DIM P%( 1 ,N)'Integer-Feld anlegen
CLS 'nicht nur sauber, sondern pixeltief rein
FOR 1=0 TO N
P%(0,I)= RND(Xmax)' X-Wert erzeugen
P%(1,I)= RND(Ymax)' Y-Wert erzeugen
NEXT I
PPOLYGON P%(0,N)' Polygon zeichnen
Pos=1: Distanz relativ. Wert (positiv oder negativ) geht um angegebenen Wert vor oder zurück.
Pos=2: Position wird vom Dateiende gerechnet
Das etwas komplexere Beispielprogramm lädt ein Bild im alten DEGAS-Format auf den Bildschirm. Dabei wird ebenfalls die Farbpalette berücksichtigt.
DEGAS-Format ist folgendermaßend aufgebaut:
2 Byte Auflösung
16*2 Byte Farbinformation
32000 Byte Bildinfo
Zum Auslesen der Farbinfo wird also der Dateizeiger auf 2 gesetzt, zum Einladen des Bildes auf 34.
Um in Programmen mit Speicherbereichen spielen zu können, sind vier neue Befehle hinzugekommen. Die ersten zwei dienen der Speicherverschiebung, nicht mit BITBLT zu verwechseln, wobei der einzige Unterschied zwischen ihnen ist, daß der eine wortwei-se, daher schneller, und der andere bytebezogen arbeitet.
MEMORY_MOVE bzw.
MEMORY_MOVEB<Start>,<länge> TO <Ziel>
Bei _MOVE ist auf drei gerade Werte zu achten, da sich der Prozessor sonst beschwert.
Dieser Befehl ähnelt MEMORY, doch wird der Speicher nicht vom GEMDOS reserviert, sondern direkt im BASlC-Programm angelegt. Somit können Daten mit dem Programm abgespeichert werden.
MEMORY_BLOCK <Nr.>,<Länge>,<Adresse>...
...reserviert soviele Bytes, wie in Länge angegeben sind, und übergibt der Variablen Adresse die Adresse, über die auf den Block zugegriffen werden kann. Nummer muß eine zweistellige Zahl (00-99) sein. Es können also bis zu 100 Blöcke definiert werden. Eine Anwendung wäre beispielsweise das direkte Einbinden von Sprite -Daten, sie müßten dann nicht mehr nachgeladen oder in DATA-Zeilen abgelegt werden.
Die Adresse eines Datenblocks liegt nicht fest, absolut adressierende Maschinenprogramme können auf diese Art nicht eingebunden werden.
Da das Erzeugen eines solchen Blocks etwas komplizierter ist, empfehlen wir folgendes Schema:
MEMORY_BLOCK <Nr>,<Länge>,<Adresse>
Zunächst mit einen Block reservieren
BLOAD "Dateiname",Adresse:STOP
Die Daten werden in den Block geladen und das Programm gestoppt.
Danach die BLOAD-Zeile entfernen oder mit REM versehen. Der Datenblock befindet sich nun im BASIC-Code.
Bei Verwendung des klassischen MEMORY-Befehls fehlte bislang die Möglichkeit, diesen wieder freizugeben. Der Befehl
FRE(<Adresse>)
erledigt dies prompt. Adresse muß die Adresse sein, die beim Memoryaufruf zurückgegeben wurde. Es sollte aber beachtet werden, daß GEMDOS nicht beliebig viele Memoryaufrufe verkraften kann.
Eine kleine, doch sehr nützliche Änderung wurde im Sort-Befehl realisiert. Häufig kam es vor, daß man in einem hoch dimensionierten Feld nur wenige benutzte. Ein folgender SORT-Befehl nahm keine Rücksicht auf die leeren Felder.
Mit
SORT <Feldname>(<Anzahl>)
ist es nun möglich, nur bis zum Index (Anzahl-1) zu sortieren. Beträgt der Parameter Anzahl Null, so wird das gesamte Feld sortiert.
Bei den Aufrufen von GEMDOS, BIOS, XBIOS oder CALL wurde bislang die Aufteilung in HIGH- und LOW-Byte gefordert - nun sind auch Langworte erlaubt. Dem übergebenen Wert wird dabei ein L vorausgestellt. Das Beispiel lädt den Bootsektor der Diskette ein, stellt ein RTS ($4E75) an den Anfang und schreibt ihn wieder zurück. Es handelt sich hierbei um einen einfachen Viruskiller, der beim Booten bewirkt, daß das Bootprogramm nicht ausgeführt wird. Wenden Sie es nie bei TOS-Disketten oder selbststartenden Programmen (meist Spiele) an!!! (Siehe Beispiel MINI-VIRUS-KILLER OMIKRON auf der nächsten Seite).
Als geradezu revolutionär kann man den LIBRARY-Be-fehl bezeichnen. Er ermöglicht
' INLINE
' Beispiel für s/w und mittlere Auflösung
PRINT CHR$(27);"P" ' Cursor aus
BLOAD "c:\utility\joshua\joshua.pic"' 32000K-Bild laden
'Falls kein Bild vorhanden, tut's auch Text
'FOR 1=0 TO 23: PRINT "O wie soft ist mein Scroll": NEXT I
FOR 1=0 TO 24
INLINE "3f3c00024e4e548f343c000f323c03e5204043e800504
. cd938f848d038f841 e8002051 c9fff251 caffe44e75"
' 8 Pixel nach oben scrollen
NEXT I
Start: move.w #$2,-(sp) ;3f3c 0002
trap #$e ;4e4e
addq.l #$2,sp ;548f
move.w #$f,d2 ;343c 000f
loop1: move.w #20*399/8,d1 ;323c 03e5
movea.l d0,a0 ;2040
lea.l $50|a0),a1 ;43e8 0050
loop: movem.l (a1)+,d3-d7/a3-a5 ;4cd9 38f8
movem.l d3-d7/a3-a5,(a0) ;48d0 38f8
lea.l $20(a0),a0 ;41e8 0020
dbra d1,loop ;51c9fff2
dbra d2,loop1 ;51ca ffe4
ende: rts ;4e75
'OPEN "U"
'
XBIOS (Bildschirm,2)
OPEN "U",l,"A:\MOUNTAIN.PI3"' DEGAS-Pic
IF LOF(1)=32034 THEN
DIM(16)
SEEK 1,2' Zeiger auf Farbinfo
GET 1 ,Farb$,32’ Farbpalette lesen
FOR C=0 TO 15
C(C)= CVI( MID$(Farb$,C*2+l ,2))' AND $777
PALETTE C(0),C(1),C(2),C(3),C(4),C(5),C(6),C(7),C(8),
C(9),C(10),C(11),C(12),C(13),C(14),C(15)
NEXT C
ENDIF
SEEK 1,34' altes DEGAS-Format
GET 1 .Bildschirm,32000' Bildinfo laden
CLOSE 1
REPEAT UNTIL INKEY$ <>“"
'PALETTE $777,0' falls ungünstige Farbkombination
MEMORY_MOVE, MEMORY_MOVEB
das Einbinden einer speziell gepackten Bibliothek in das eigene Programm. Als Beispiel kann man die neue GEM-Lib der Version 3.00 betrachten. Bislang mußte sie ‘einge-mergt’ werden, was erstens längere Zeit in Anspruch nahm (Wer hat die schon?) und zweitens einige hundert Zeilen belegte. Mit LIBRARY belegt sie nurmehr eine Zeile und wir in ca. 4 Sekunden von Disk geladen. Einmal geladen, bleibt die Library im BASIC-Code enthalten und wird mit dem Programm abgespeichert.
LIBRARY <Proc>,<Name>
bindet eine Library in den Basiccode. Die Library selbst erscheint im Programmtext nurmehr als eine Zeile in Form von LIBRAY CODE <Proc>. Diese Zeile stellt die nachgeladene Library dar, es werden also nicht wie mit MERGE alle Zeilen explizit dargestellt.
Beispiel:
LIBRARY GEM,"A:\GEM.LIB"
lädt die speziell gepackte GEMLIB (ab Interpreter V 3.00). Sie erscheint am Programmende in der Form:
LIBRARY CODE GEM
Leider ist es dem Anwender zur Zeit noch nicht möglich, eigene Routinen in eine LIBRARY zu verwandeln (dafür wird es demnächst einen Library-Maker geben), aber alleine für GEMLIB und die anderen OMIKRON.Libraries ist dies ungeheuer praktisch.
** MINI-VIRUSKILLER - OMIKRON **
Mem= MEMORY(512)
XBIOS Dummy,8,L Mem,L 0,0,1,0,0,11 ' Block lesen
WPOKE Mem,$4E75' RTS
XBIOS Dummy,9,L Mem,L 0,0,1,0,0,1' Block schreiben
Eine neue Systemvariable wurde eingeführt - COMPILER.
Wird mit Compiler gearbeitet, kann es wichtig sein, bestimmte Programmteile von der Übersetzung, bzw. vom Programmlauf auszuschließen.
Dazu kann die Systemvariable Compiler benutzt werden.
COMPILER ohne Parameter liefert -1, wenn das Programm in compilierter Form abläuft. COMPILER {ONIOFF} ermöglicht das Überspringen ganzer Programmteile beim Compilieren.
COMPILER <Stringausdruck>:
Im Stringausdruck werden die Compileroptionen durch Semikolon getrennt angegeben.
Beispiel:
COMPILER "Trace_On"
ersetzt die bisherige Syntax:
Trace On: IF 0 then DEF PROC Trace_On: RETURN
Der Interpreter, schlau wie er ist, ignoriert diesen String.
wird als ILLEGAL compiliert und löst somit im Programmlauf eine Exception über den ILLEGAL-Vektor aus. Sinn der Sache ist, daß man damit an einer bestimmten Stelle in einen im Hintergrund laufenden Debugger springen kann.
ist eine Systemvariable, die die Adresse des reservierten Speicherbereiches zurückgibt.
RESERVED(<Nummer>)
Die Nummer gibt den Offset an. Dokumentiert sind nur die Nummern 0 und 4.
Mit
PRINT LPEEK(RESVERED(0))
kann der Rückgabewert einer mit CALL aufgerufenen Prozedur (DO) ausgegeben werden. Es wird der letzte Wert vom Register DO zurückgegeben.
POKE RESVERED(4), 1
unterbricht INPUT USING in compilierten Programmen sofort. Allerdings muß Multi-tasking_AIways aktiv sein.
Der Returnwert von INPUT USING beträgt dabei -3.
Systemvariable, die die Versionsnummer des Interpreters liefert.
Erscheint jetzt 300 auf dem Bildschirm, haben Sie Version 3.00 von OMIKRON.BASIC. Bitte achten Sie auf die Doppel-Null.
FSEL_EXINPUT
Es ist Ihnen sicherlich schon zu Gehör gekommen, daß das TOS 1.4, das sich zur Zeit noch in Entwicklung befindet, eine erweiterte Fileselector-Box bietet, die die Übergabe einer Kommentarzeile ermöglicht. Der Anwender weiß dadurch, was in der Box gerade ausgewählt werden soll (z.B. ‘Datei Laden’ oder ‘Speichern als’). Die GEMLIB der Version 3.00 beinhaltet diese Routine.
Fsel_Exinput <Pfad>,<File_Name>,-<AusgabeString>, <Rückgabewert>
Ausgabestring stellt den Text dar, der oben in die Fileselektorbox geschrieben werden soll, Rückgaben ert=l bedeutet, daß OK angewählt wurde, Riickgabewert=0 steht für ABBRUCH. Um die Lauffähigkeit unter alten TOS-Versionen nicht einzuschränken, wird dieser Funktionsaufruf bei älteren TOS-Versionen (immerhin 99,9% der jetzigen Anwender) emuliert, was soviel heißt wie, daß zusätzlich zur gewöhnlichen Fileselektorbox eine Box mit dem Ausgabestring geöffnet wird. Beachten Sie, daß für Fsel_Exinput die GEMLIB eingeladen sein muß.
Viel Spaß beim Austesten.
WSIHS