Ausgewählte TOS-Befehle in Pascal

Das Betriebssystem des ST beinhaltet viele Routinen, mit denen man die Fähigkeiten des Rechners erst richtig nutzen kann. Die Routinen des Betriebssystems, sei es BIOS, XBIOS oder GEMDOS, sind sehr leistungsfähig und für einige Programmieraufgaben fast unumgänglich. Sie sollen deshalb hier näher vorgestellt und analysiert werden.

Höhere Programmiersprachen enthalten solche Systemaufrufe meist nicht im Sprachstandard, da diese bei jedem Rechner bzw. Betriebssystem unterschiedlich sind. Beim ST gibt es aber trotzdem eine Möglichkeit, Systembefehle (TOS & GEM) aufzurufen.

Grundprinzip

Bevor eine Betriebssytemroutine aufgerufen werden kann, muß sie zuerst deklariert werden. Dies wollen wir an einem Beispiel verdeutlichen, das nebenbei noch eine im ST-Pascal nicht implementierte Funktion liefert - eine Zufallszahl.

Zuerst einmal muß die Funktion deklariert werden, dies geschieht durch:

function RANDOM : Integer ; GEMDOS (5)

Der Aufruf erfolgt dann einfach durch:

writeln( RANDOM )

Listing 1 zeigt das dazugehörige Programm:

program RANDOM;

var ch : char;

function RANDOM_INT	;	integer;	xbios(17);
function RANDOM_LONG	:	long_integer; xbios(17);
function RANDOM__REAL	:	real;	xbios (17} ;
function RANDOM_CHAR	:	char;	xbios(17);
function RANDOM_BOOL	:	boolean;	xbios(17);
begin
repeat
writefehr(27),'E'); 
writeln(RANDOM_INT); 
writeln(RANDOM_LONG); 
writeln(RANDOM_REAL); 
writeIn(RANDOM_CHAR); 
writeln(RANDOM_BOOL); 
read(ch);
until Ch<>' ';

end .

Listing 1

Das System gibt eine 24-Bit Zufallszahl zurück; je nach gewähltem Datentyp der Deklaration kann man aber trotzdem jeden Datentyp zurückerhalten.

Die Parameterübergabe erfolgt wie in normalen Pascal-Funktionen/Prozeduren. Der Befehl 'GEMDOS (x)’ sorgt für den Aufruf des GEMDOS Befehls. Entsprechend ist die Deklaration der XBIOS und BIOS Routinen.

Anmerkung: Die Beispiele wurden vorwiegend mit CCD-Pascal von Atari erstellt. Eine Übertragung auf andere Compiler ist aber kein Problem, falls Betriebssystemaufrufe dort möglich sind.

Der Bildschirm

Wie die Überschrift schon vermuten läßt, dreht es sich im nächsten Abschnitt um Befehle, die auf den Bildschirm zugreifen. Man kann sie als Ergänzung zu den normalen’ Grafikbefehlen sehen.

Beispiel: Sie haben ein Diagramm erstellt und wollen es zur späteren Ansicht auf Diskette sichern. Dazu benötigt man zuerst die Anfangsadresse der Grafikseite. Nun, diese liegt nicht bei jedem Rechner gleich (siehe Tabelle 1).

Rechner Anfangsadresse d. Bildschirms 1 Mega 1015808 512 k 491519 ROMs wie der entspr. Rechner

Tabelle 1

Zwar kann man die Adresse für seinen Rechner in Erfahrung bringen und diese direkt angeben; es ist aber eine unschöne Art, den ST zu programmieren, das nebenbei noch zu Inkompatibilität der Software führt. Beweise dafür gibt es auch im Bereich der 'professionellen' Software. Sogar dort kam es vor, daß ein Programm mit einer neuerschienenen TOS-Version - das ist nun endlich vorüber - nicht mehr lief. Der Grund dafür war meistens der direkte Zugriff auf Speicherstellen, die in der neueren Version an einer anderen Stelle lagen. Um dies zu vermeiden, sollte man die entsprechenden Routinen benutzen, die dann automatisch die jeweils passenden Werte liefern. Am Beispiel der Bildschirmadresse sieht man, daß dies ganz einfach ist. Die Routine LOGBASE liefert die Adresse, bei der der Bildschirm beginnt (siehe Listing 2).

Mit dem daraus gewonnenen Wert kann man die Routinen zum Bildschirmspeichern bzw. -lesen ansprechen.

Doch zuerst noch ein paar Worte zu den Grafikseiten im ST. Es ist möglich, mehr als nur die eine sichtbare Grafikseite im Rechner anzulegen und zu verwalten. Mit einem Systemaufruf (SETSCREEN) läßt sich dann jede Seite anwählen bzw. zur sichtbaren erklären.

Der ST muß dabei zwischen der sichtbaren Seite und den anderen unterscheiden können. Dafür gibt es die Funktion PHYSBASE (Listing 3).

Sie zeigt auf den Speicherbereich, der momentan auf dem Bildschirm abgebildet wird. Der Wert dieser Funktion ist also normalerweise mit dem der Funktion LOGBASE identisch, denn es wird meistens auf der Bildschirmseite gearbeitet, die auch angezeigt wird. LOGBASE muß aber nicht zwangsweise auf die sichtbare Bildschirmseite zeigen, sondern auch auf eine beliebige andere ist möglich. Auf dieser Seite werden dann alle Bildschirmanweisungen (z. B. Text- und Grafikbefehle) ausgeführt. Der Systemaufruf SETSCREEN ermöglicht es, nun eine bestimmte Bildschirmseite anzuzeigen und auf einer anderen zu zeichnen, oder aber zwischen verschiedenen Seiten umzuschalten (siehe z. B. DEGAS). Im Beispiel (Listing 4) werden zwei zusätzliche Grafikseiten erzeugt und nacheinander aktiviert.

SETSCREEN verlangt als Parameter die Speicheradresse des logischen und physikalischen Bildschirms.

program Bildschirm_logisch;
function LOGBASE : long_integer; xbios(3);

begin
	writeln(LOGBASE );
	readln
end.

Listing 2

program Bildschirm_physikalisch;

function PHYSBASE : long_integer; xbios(2);

begin
	writeln(PHYSBASE );
	readln
end.

Listing 3

($S5)	 ( Lebensnotwendig )

program setscreen:

var bild1,bild2,lognorm.physnorm : long_i nteger ;
a : integer;

procedure setscreen (logisch,phys: long_integer;rest: integer); xbios(5):
function logbase: long__integer; xbios(3);
function physbase : long_integer; xbios(2);
function malloc	(wieviel:long_integer) :long_integer ; gemdos ($46);

begin
	lognorm :=logbase:  { Normalwerte sichern	}
	physnorm := physbase; {	"	}
	if malloc (-1) > 2*32255 then begin {Platz fuer 2 Bilder ? }

		bild1:-ma11oc(32255)+255;	{ Speicher reservieren }
		bild1:=bild1 - (bild1 mod 256);	 { auf 256'er vAdresse setzen }

		bild2;-mal loc(32255)+255:	 { " }
		bild2:-bild2 - (bild2 mod	256):	{ " }

		writeln (chr(27),’E	Dies ist der normale Bildschirm’);
		for a:=0 to 10 do writeln ('Hallo‘);
			writeln ('	bitte	RETURN druecken');
			setscreen (bild1. bild1,-1) { Ausgabe auf Bild 1 lenken }
			writeln (chr(27),'E	Dies ist der zweite Bildschirm’);
			for a:=0 to 639 do put_pixel (a,200-round(50*sin(a/20)), 1) ;

			setscreen (bild2, bild2,-1):	{ Ausgabe auf Bild 2 lenken }

			writeln (chr(27),”E	Dies ist der dritte Bildschirm');
			for a:=0 to 639 do
				line(a,200,a,trunc(sin(a/20)* 100+200),1,1,1,1,$ffff,0) :
				for a:=0 to 5 do begin
					setscreen (-1.physnorm.-1);{ Normalbild zeigen }
					readln ;
					setscreen (-1, bild1,-1);	{ Bild 1 zeigen }
					readln :
					setscreen (-1. bild2,-1);	{ Bild 2 zeigen }
					readln: 
				end 
			end

		else begin
			writeln (' Zu wenig Speicher fuer zwei neue Bildschirme ');
			readln;
		end;
		setscreen (lognorm, physnorm, -1) ; { Normalzustand herstellen }
						{ sonst sehr uebel }
	end .

Listing 4

program Grafikaufloesung: 

	var res : byte;

	function GETREZ: integer; xbios(4);

	begin
		write('SIE arbeiten in der ')
		case GETREZ of
			0 : writelnt('niedrigen (sehr bunten) Aufloesung');
			1 ; writeIn(' mittleren (bunten) Aufloesung’);
			2 ; writeln(’hohen (monochromen) Aufloesung ');
		 end;
		readln
	end.

Listing 5

{$S1} { reserviert etwas Speicher }

Program MALLOC;

function MALLOC (groesse:long_integer): long_integer; gemdos ($48);

var groesse, adresse: long_integer;

begin
	groesse:= 1000;
	adresse:= MALLOC( Groesse ):
	writeln ( SIE haben einen '.groesse.' Byte grossen Bereich ab Adresse ', adresse,' reserviert')
end.

Listing 6

{$S1}	{ reserviert 1K Speicher }
program MALLOC;

function MALLOC(groesse: long_ integer) : long__integer; gerndos ( $48) ; 

begin
	writeln('SIE haben noch '.MALLOC(-1),' Byte freien Speicher !');
 end.

Listing 7

Bei SETSCREEN taucht noch ein weiterer Parameter auf - die momentane Bildschirmauflösung. Diese ist beim Farbmonitor 0 oder 1, beim Monochrommonitor 2. Erfragt werden kann die Auflösung mit der Funktion GETREZ (get resolution). Ein einfaches Beispiel dafür ist Listing 5 zu entnehmen.

Wenn man bei der Prozedur SETSCREEN einen Parameter nicht ändern will, so schreibt man anstelle des Wertes eine ’ —1’ in den Prozeduraufruf, z. B. Anzeigen einer anderen Bildseite:

setscreen (-1,neues__bild,-1)

Der logische Bildschirm und die Auflösung werden nicht verändert. Nebenbei kann man durch Umschalten der Auflösung, z. B. von Färb- auf Monochrombetrieb den Rechner schön ’in die Wüste schicken’.

Das Beispielprogramm SCREEN (Listing 6) zeigt die prinzipielle Nutzung aller Prozeduren bzw. Funktionen, je nach Anwendung kann man spezielle Prozeduren gestalten, beispielsweise ’SWITCH____SCREEN’ oder ’SHOW_SCREEN’. Als weitere Anregung sei das Umschalten der Bildschirme mit der Maus genannt, doch dazu später.

Wichtig: bevor man das eigene Programm verläßt, sollte man unbedingt die logische und physikalische Adresse wieder angleichen, da sonst der Effekt einem Absturz nahe kommt (Wo ist bloß die Maus??).

Um Speicherplatz für andere Grafikseiten zu reservieren, ruft man die Systemroutine MALLOC auf. Dazu wird der Funktion die Größe des Speichers in Byte übergeben (Listing 7).

Die Funktion liefert dann die Anfangsadresse des reservierten Bereiches. Bei Verwendung als zusätzliche Bildschirmseite, sollte beachtet werden, daß der Videochip nur Adressen in 256-Byte-Schritten akzeptiert, andernfalls erscheint das Bild verschoben.

Wie aus dem Programm SCREENS ersichtlich, kann mit einer kleinen Verknüpfung die Anfangsadresse auf eine dem Videochip genehme Adresse (n-*256) gelegt werden. Dazu wird ein kleiner Puffer belegt, der die Verschiebung auffängt (max. 255 Bytes).

Anmerkung: Da die Funktion MALLOC keinen Speicher bereitstellt, wenn die gewünschte Größe nicht mehr verfügbar ist, sollte der Benutzer diesen möglichen Fehler entsprechend abfan-gen. Dies ist z. B. durch einen Aufruf der Routine mit dem Wert -1 möglich, denn dann wird der noch freie Speicherplatz (in Byte) zurückgegeben.

Doch nun zum ersten Programm, das die bis jetzt vorgestellten Prozedur- und Funktionsaufrufe verwendet. Das Programm SCREENS schreibt auf drei verschiedene Bildschirme und schaltet anschließend zwischen ihnen hin und her.

Da in dem Programm die Funktion MALLOC aufgerufen wird, wird erst einmal 5k Speicher reserviert ([$S5J). Danach werden die Adressen des logischen und physikalischen Speichers gesichert, weil sie vor Verlassen des Programms wieder auf diese Werte eingestellt werden müssen. Ansonsten ist es möglich, daß auf eine andere Seite geschrieben wird als auf die angezeigte.

Der nächste Schritt dient der Überprüfung, ob genügend Speicherplatz vorhanden ist, um zwei weitere Bildschirmseiten zu verwalten. Ist dies nicht der Fall, wird das Programm abgebrochen.

Als nächstes werden die Anfangsadressen der neuen Bildschirmseiten ermittelt. Sie werden in den Long__Integer Variablen bildl und bild2 abgelegt.

Das Programm schreibt nun auf den 'normalen’ Bildschirm, schaltet auf den zweiten um, beschreibt diesen usw. Danach kann durch Drücken von < Return > zwischen den Seiten umgeschaltet werden.

Beim Experimentieren mit mehreren Bildschirmen findet man schnell heraus, daß bei Überschreiben des Bildschirmrandes auf die benachbarte Grafikseite gezeichnet wird. Deshalb ist es ratsam, den Ausgabebereich mit der Funktion set___clipping zu begrenzen, falls nämlich keine zweite Grafikseite angrenzt, kann eine solche Überschreitung des Bildschirmes leicht zum Erzeugen der bei allen ST-Besitzern so beliebten Bomben führen.

Vermieden wird dies durch folgenden, im ST-Pascal vorhandenen, Aufruf:

Set__clipping (true,xmin,ymin,xmax,ymax)

Ein Absichern des gesamten Bildschirmbereiches geschieht folglich durch:

Set__clipping (1,0,0,639,399)

Soviel für dieses Mal - leider reicht der Platz nicht mehr. In den nächsten Teilen wird das Laden und Speichern von Grafikbildern besprochen, sowie einige Befehle zu den Themen FLOPPY, Sound und neue Farbroutinen.

Falls Ihnen etwas zu den vorgestellten oder angekündigten Themen oder zu anderen Pascal-Tricks einfällt, so lassen Sie es uns hören.

Wir würden uns über Ihre Beteiligung sehr freuen.

(MN & HS)



Aus: ST-Computer 10 / 1986, Seite 82

Links

Copyright-Bestimmungen: siehe Über diese Seite