Der TT hat bei vielen Accessories ein besonderes Problem: Sie vertragen keinen Auflösungswechsel. Das Warum haben wir genauer untersucht. Doch zuerst ein kleiner Abstecher in Ataris Fehlerbehandlung.
Jedes Betriebssystem hat Fehler. Genausowenig wie irgendein anderer Hersteller, hat es Atari bislang geschafft, ein völlig fehlerloses Release hinzubekommen. Und so war es auch nicht die Frage, ob, sondern nur wann man auf die ersten Ungereimtheiten im »TOS 3.01« des »TT« stoßen würde.
Bei Redaktionsschluß waren uns folgende TT-TOS-spezifischen Probleme bekannt:
Die Feldlänge wird mit Hilfe der »extended inquire function« abgefragt. Und hier lauert der Fehler: Das VDI behauptet, Platz für 512 Koordinatenpunkte zu haben - tatsächlich aber reicht er nur für 256 Punkte. Die Folge: In Zusammenhang mit »AMCGDOS 4« (im Lieferumfang von »Scigraph 2.0«) kann nicht die maximale Qualität der Bezier-Kurven genutzt werden. Abhilfe schafft das Auto-Ordner-Programm »PTSINFIX«, das den Fehler behebt (zu beziehen z. B. aus der Maus MS, 0251/77261, und von der Scilab GmbH, Hamburg).
Und man staune: Atari hat die einlaufenden Fehlermeldungen zur Kenntnis genommen, die Fehler beseitigt und liefert den TT seit kurzem mit der aktualisierten TOS-Version 3.05 aus. Wenn das keine umwerfende Verbesserung gegenüber der Lethargie früherer ST-Jahre ist!
Und nun zu einem Bereich der GEM-Programmierung, bei dem es besonders viele Fallstricke zu beachten gilt: die Programmierung von Accessories. Viele TT-Besitzer haben schon die schmerzliche Erfahrung gemacht, daß liebgewonnene Helfer spätestens bei einem Auflösungswechsel den Geist aufgeben. Dies ist kein neues Problem - doch wer hat schon früher häufiger zwischen den Auflösungen hin- und hergeschaltet?
Der Knackpunkt ist, daß bei einem Auflösungswechsel der vom Accessory belegte Speicherplatz freigegeben wird. So ist es mit sauberen Mitteln praktisch unmöglich, innerhalb von Accessories Vektoren zu verbiegen. Mit seinem Accessory »Chameleon« hat Karsten Isakovic ([2]) gezeigt, daß es dennoch geht - wenn auch nur durch einen gewaltigen Programmieraufwand. Wer sich also in Vektoren hängen will, sollte dies im Auto-Ordner tun - ein GEMgestütztes Konfigurationsprogramm kann dann über den Cookie-Jar mit dem Vektorverbieger Kontakt aufnehmen (genauso macht es z. B. Atari-Programmierer Ken Badertscher bei seinem Mausbeschleuniger »Macce13«).
Daß Accessories keine GEMDOS-Prozesse sind, ist der Grund für die meisten anderen Schwierigkeiten. Ein Accessory, das GEMDOS-Aufrufe tätigt, macht dies immer unter der Prozeßkennung des gerade laufenden Hauptprogramms. So muß man bei allen GEMDOS-Aufrufen, bei denen prozeßinterne Daten verändert werden, sehr genau aufpassen.
Beginnen wir mit der Speicher- und Dateiverwaltung. Jeder Speicherblock, den man anfordert, und jede Datei, die man öffnet, gehört dem Hauptprogramm. Sobald dieses beendet wird, werden die Speicherblöcke freigegeben und die Dateien geschlossen. Besondere Gefahr: Bei GEM-Versionen vor 3.0 (TT-TOS) ist nicht garantiert, daß man die »AC_CLOSE«-Mitteilung tatsächlich vor der endgültigen Beendigung des Hauptprogramms bekommt. Eventuell geöffnete Dateien muß man also als geschlossen, allozierte Speicherblöcke als verloren ansehen!
Es gibt allerdings einen Trick, mit dem man solche Verluste verhindern kann und der in letzter Zeit in verschiedenen Fachzeitschriften beschrieben wurde: Gemeint ist das Umschalten des GEMDOS-Prozesses über den »act_pd«-Zeiger. Der schreibende Zugriff auf diesen Zeiger ist allerdings ausdrücklich als verboten dokumentiert!
Probleme gibt es auch im Zusammenhang mit »Fsfirst()«, »Fsnext()«, »Fsetdta()« sowie »Fgetdta()«. Zunächst muß man bedenken, daß sämtliche von Fsfirst() und Fsnext() veränderten Daten in der DTA des Hauptprogramms landen. Deshalb darf man diese Funktionen in Accessories nur dann benutzen, wenn man zunächst die alte DTA-Adresse abfragt, eine neue DTA installiert und dann nach Abschluß der Fsfirst()/Fsnext()-Aufrufe die alte DTA wiederherstellt.
Unerträglich wird es im Zusammenhang mit »verdeckten« GEMDOS-Aufrufen. In vielen Hochsprachenbibliotheken lauern z. B. unerwartete »Malloc()«- oder »Fsfirst()«-Aufrufe. Hier ist äußerste Vorsicht geboten, der Systemmonitor »Sysmon« [3] kann dann bei einer Fehlersuche wertvolle Hilfe leisten.
Auch bei VDI-Funktionen ist Vorsicht geboten: Ein Aufruf von »Open Virtual Workstation« führt zu einer Speicherreservierung via Malloc(). VDI-Workstations darf man nämlich nur entweder gleich nach Start aufmachen (und muß sie dann auflassen) oder sie nur temporär auf und dann sofort wieder zumachen. Wenn man übrigens innerhalb des Accessory keine VDI-Funktionen braucht, sollte man logischerweise auch keine Workstation öffnen!
Bitte nicht vergessen: Der AES-Dispatcher kann bei jedem AES-Aufruf zwischen Hauptprogramm und Accessories umschalten, und das ist keineswegs irgendwie mit Aufrufen der Event-Funktionen verknüpft! Daher muß man mit Hilfe von »wind_update()« selbst dafür sorgen, daß nicht im falschen Moment eine Prozeßumschaltung stattfindet. Ein Beispiel finden Sie in unserem Listing.
Auch bei der Auswertung der im Programmkopf befindlichen Flags (siehe in [4]) werden Accessories nicht wie vollwertige GEM-DOS-Prozesse behandelt. Während Bit 0 (»Fastload«) und Bit 1 (darf in TT-RAM gelesen werden) Beachtung finden, wird Bit 2 (Mallocs aus TT-RAM erlaubt) ignoriert. Grund: GEM-DOS legt diese Information an einer reservierten Position in der Basepage ab. Da bei Accessory-Aufrufen jedoch die Basepage des Hauptprogramms aktiv ist, geht diese Information de facto verloren.
Wissenswert auch, daß sich das AES bei Prozeßumschaltungen genausowenig um die 68882-Register im TT wie die 68881-Register in STs mit einer FPU-Karte kümmert. Accessories dürfen daher normalerweise auf gar keinen Fall die FPU benutzen!
Viele Programmierer ignorieren übrigens wichtige Return-Codes ganz bzw. interpretieren sie nicht ganz richtig. Tatsache ist, daß einige AES-Funktionen auch mangels Speicher fehlschlagen können. Zwei Beispiele:
Die Funktion »rsrc_load()« liefert nicht nur dann einen Fehler, wenn die RSC-Datei nicht gefunden wurde. Auch wenn der vom AES abgesetzte Malloc()-Aufruf zu einem Fehler geführt hat, gibt es eine Fehlermeldung. Ein vorausschauendes Programm sollte im Fehlerfall mittels »shel_find« feststellen, ob die RSC-Datei auch wirklich fehlt und nur dann die Alertbox »RSC-Datei nicht gefunden« präsentieren. Anderenfalls sollte man den Benutzer auf die anderen möglichen Ursachen (Datei kaputt, zu wenig Speicher) hinweisen.
ähnliches gilt für »fsel_input()« (und »fsel_exinput()«). Auch bei dieser Funktion fordert das AES Speicher an, und ebenso wie bei »rsrc_load« führt Speichermangel zu einer Fehlermeldung! Der Themenschwerpunkt »Accessories« führt fast zwangsläufig zum Reizthema »modulares Kontrollfeld«. Das neue Kontrollfeld ist sicherlich eine attraktive Erweiterung der Systemsoftware. Der eigentliche Sinn der Sache sollte wohl sein, daß immer mehr Accessories, die nur Konfigurationsaufgaben übernehmen, von »XCONTROL«-Modulen ersetzt werden. In dieser Hinsicht hat es allerdings noch keinen Fortschritt gegeben. Zunächst einmal gibt es bis heute keinerlei Dokumentation zum modularen Kontrollfeld. Wer im Moment ein »CPX« (Control panel extension) programmieren wollte, müßte erst einmal ein vorhandenes CPX disassemblieren.
Des weiteren darf XCONTROL z.Z. nur an TT- und Mega-STE-Besitzer weitergegeben werden - als wenn man Besitzer alter Rechner durch die »Exklusivität« von XCONTROL zum Kauf eines neuen Computers animieren könnte. Pikanterweise verbreitet Atari Benelux XCONTROL über die hauseigene Mailbox (Telefonnummern 0031/347377584 und 0031/ 347377376), wo es sich (gemessen an der Zahl der Downloads) einer großen Beliebtheit erfreut.
Auf telefonische Anfrage teilte uns Dr. Hans Riedl (Leiter Software bei Atari Raunheim) kurz vor Redaktionsschluß mit, daß sich Atari Deutschland darum bemüht, XCONTROL auch allen bisherigen ST-Kunden zugänglich zu machen.
(uw)
/* Beispiel für GEMDOS-Aufrufe innerhalb von Accessories */
long get_size (const char *filename)
{
DTA *oldDTA; /* Speicher für alten DTA-Zeiger */
DTA newDTA; /* Platz für eigene DTA */
int result;
wind_update (BEG_UPDATE); /* keine AES-Switches */
oldDTA = Fgetdta (); /* alten Zeiger merken */
Fsetdta (&newDTA); /* neue DTA installieren */
result = Fsfirst (filename, 0);
Fsetdta (oldDTA); /* wieder alte DTA */
wind_update (END_UPDATE);
if (result) /* Fehler bei Fsfirst() */
return -1L;
else
return newDTA.d_length;
}