Beim Arbeiten mit den MiNTLibs auf dem Falcon030 stellte ich fest, daß ohne MiNT die Ausgaben auf stderr nie erscheinen. Ein Fehler in den MiNTLibs lag nahe, doch bereits nach kurzer Zeit war klar: Das GEMDOS hat einen Fehler! Der Aufruf Fforce(2, -7), der normalerweise fehlerfrei funktioniert, wird auf dem Falcon mit EIHNDL (ungültiges Handle) quittiert. Eine Sache, die schnell beseitigt werden kann, dachte ich, und machte mich an die Arbeit, doch ich sollte schnell eines Besseren belehrt werden.
Die Sache begann kompliziert zu werden, als ich feststellte, daß nicht nur der Fforee-Aufruf Probleme mit den negativen Geräte-Handles hat. Sämtliche GEMDOS-File-Funktionen (die mit negativen Handles arbeiten) verweigern auf dem Falcon die Arbeit mit diesen Kennungen. Dies ist auch der Grund, warum GFA-BASIC nicht mehr drucken kann, denn intern wird dazu Fwrite(-3, ...) benutzt, was leider auch mit „ungültiges Handle" abgelehnt wird (siehe auch [1]). Damit ist GFA-BASIC in dieser Hinsicht rehabilitiert, denn ich war sicherlich nicht der Einzige, der den Fehler auf eine unsaubere Programmierung des Interpreters zurückgeführt hat.
Ein Blick in [2] zeigte, daß die negativen Gerätekennungen auf jeden Fall dokumentiert sind. So sollte beispielsweise ein Aufruf von Fopen("PRN:",1) die Kennung -3 liefern. Das Falcon-GEMDOS vergibt hierfür aber ein völlig normales Datei-Handle (also >= 6), doch zum Glück funktioniert wenigstens die Ausgabe darauf.
Was kann man da machen? Auf jeden Fall ist es notwendig, sich in den GEMDOS-Trap einzuhängen und die File-Funktionen abzufangen. Doch irgendwie muß man aus den negativen Geräte-Handles ja etwas machen, das der Falcon akzeptiert und was noch dazu auch den gleichen Effekt hat.
Der erste Vorversuch bestand darin, einmal Fforce(2,Fopen("CON:", 2)) zu testen, und siehe da: Keine Fehlermeldung, und Ausgaben auf stdaux kamen tatsächlich auf den Bildschirm! Also müßte man nur die drei zeichenorientierten Geräte CON:, PRN: und AUX: per Fopen öffnen und in den abgefangenen GEMDOS-Funktionen die negativen Geräte-Handles durch den jeweiligen Fopen-Wert ersetzen. Nur ein „klitzekleines" Problem ist da noch: Das GEMDOS verwaltet die Gerätekennungen separat für jeden Prozeß, also kann man die Fopen-Handles nicht einmal ermitteln und dann global für jeden Prozeß benutzen. Tja, was tun?
Irgendwie muß man für jeden Prozeß zwei Dinge speichern: a) wurden schon Ersatz-Handles ermittelt (man kann ja schließlich nicht beliebig oft Fopen aufrufen) und b) wie lauten diese Ersatz-Handles? In der Basepage geht's nicht, weil es da ja keine dokumentiert freien Plätze gibt, und irgendwelche Informationen überschreiben ist auch nicht drin. Als letzte und sicherlich auch geeignetste Lösung bleibt die Verwaltung dieser Informationen in einer eigenen Tabelle. Die Zuordnung, welche Handles zu welchem Prozeß gehören, erfolgt über die Adresse der Basepage (die sich ja auf dokumentiertem Weg ermitteln läßt). Problem a) läßt sich dadurch auch relativ einfach lösen, denn wenn die Basepage schon in der Tabelle vorhanden ist, wurden schon Ersatz-Handles ermittelt (natürlich muß man dafür sorgen). Selbstverständlich muß ein Eintrag wieder freigegeben werden, sobald das dazugehörige Programm beendet wurde, denn sonst sind Probleme vorprogrammiert, wenn der nächste Prozeß die gleiche Basepage-Adresse hat. Außerdem ist so ein Überlauf der Tabelle weitestgehend ausgeschlossen.
Nochmal im Überblick: Sobald ein Prozeß eine GEMDOS-File-Funktion mit einem negativen Geräte-Handle aufruft, wird geprüft, ob dessen Basepage-Adresse schon in der internen Tabelle gespeichert ist. Wenn ja, wird die Gerätekennung durch das entsprechende Ausweich-Handle aus der Tabelle ersetzt. Ansonsten werden die drei Ersatz-Handles per Fopen erzeugt (zu diesem Zeitpunkt befindet man sich noch nicht im GEMDOS, kann also problemlos GEMDOS-Funktionen aufrufen) und samt der Basepage-Adresse in der Tabelle gespeichert. Bei einem Pterm oder Pterm0 (nicht bei Ptermres) wird, falls vorhanden, der Eintrag in der Tabelle wieder entfernt, damit nicht unnötig Platz belegt wird. Da, wie bereits erwähnt, ein Fopen (”CON:", 2) ein normales Datei-Handle liefert, sollte dies natürlich auch korrigiert werden. Also müssen zusätzlich Fopen und Fcreate abgefangen werden, wenn sie mit CON:, AUX: oder PRN: als Dateinamen aufgerufen werden (oder entsprechend kleingeschrieben, gemischte Schreibweisen lehnt das GEMDOS ab!). In diesem Fall wird dann sofort das zu dem Dateinamen gehörende negative Geräte-Handle geliefert. Entsprechend wird Fclose für negative Handles wirkungslos gemacht (es wird immer OK geliefert, was sollte auch überhaupt schiefgehen?) Wer aufmerksam gelesen hat, wird festgestellt haben, daß sich hier eigentlich die Katze in den Schwanz beißt: Die Routine soll Fopen mit Geräte-File-Namen abfangen, aber auch selbst den gleichen Fopen-Aufruf tätigen, um an brauchbare Handles zu kommen. Um diesen Konflikt zu umgehen, wird vor dem internen Fopen-Aufruf ein Rag gesetzt, das dafür sorgt, daß der nächste Fopen-Aufruf nicht beeinflußt wird. Somit wären also alle Probleme beseitigt.
Das Listing (wegen Platzmangel nur auf der Mega-Disk) zeigt das fertige Programm „F030HFIX" (ausgeschrieben: Falcon030-GEMDOS-Handle-Fix). Es prüft auch, ob das GEMDOS den Patch überhaupt braucht (in TOS 4.04 ist laut Eric Smith zumindest der Fforce-Aufruf korrigiert). Dies geschieht nicht durch Abfrage der TOS-Versionsnummer, sondern durch einen kleinen Test (welches Handle liefert Fopen "CON:",2?). Wenn MiNT aktiv ist, wird der Patch auch nicht benötigt, deshalb sollte man F030HFIX.PRG nach MiNT in den AUTO-Ordner kopieren. Der GEMDOS-Vektor wird übrigens sauber per XBRA verbogen (Kennung FHFX).
Wird das Programm (am besten durch den AUTO-Ordner) installiert, funktionieren alle MiNTLib-Programme bei Ausgabe auf stderr wieder richtig. GFA-BASIC kann wieder drucken und sicher laufen noch einige andere Programme wieder korrekt, die von diesem Fehler betroffen waren.
Literaturangaben:
[1] Marcus Gigl, Der Falcon030 und GFA-BASIC. Quicktip in ST-Computer 03/1994 (Der dort beschriebene Trick funktioniert übrigtns deshalb, weil GFA-BASIC dann nicht mehr per GEMDOS, sondern direkt per BIOS auf den Drucker zugreift. Außerdem funktionieren die genannten GEMDOS- und BIOS-Aufrufe sehr wohl, nur mancher Drucker gibt eine Zeile erst nach einem CR/LF aus.)
[2] Jankowski/Rabich/Reschke, ATARI Profibuch ST-STE-TT. SYBEX-Verlag GmbH, Düsseldorf, 1991 (Teil 1, Kapitel 2, Abschnitt 3: Kanäle/ Dateikennungen)