DS$

Aus C64-Wiki
Wechseln zu: Navigation, Suche
DS$
Format: DS$
Parameter
Einordnung
Typ: Zeichenketten-Systemvariable
Kontext: Diskettenbefehl
Aufgabe: Abfrage des Fehlerkanals des zuletzt verwendeten Diskettenlaufwerks
Abkürzung: -
Verwandte Befehle
DS


Die Systemvariable DS$ (engl. Disk Status) liefert die vollständige Meldung des Fehlerkanals jenes Diskettenlaufwerks, das zuletzt angesprochen wurde als Zeichenkette. Der Wert besteht aus durch Beistriche getrennten Informationen Disk-Statuscode (vergl. DS), Meldungstext, Track und Sektor.

Eine Wertzuweisung an DS$ ist nicht erlaubt und erzeugt einen ?SYNTAX ERROR. Ist das aktuelle Geräte nicht vorhanden, folgt dem Zugriff auf diese Systemvariable ein ?DEVICE NOT PRESENT ERROR.
Ein Ausschreiben von DS$ beispielsweise als DSTATUS$ ist für einen sprechenden Programmierstil möglich.

Detailbeschreibung[Bearbeiten]

Nach einem RUN, CLR oder Systemneustart wird ein erstmaliges Auslesen des Fehlerkanals erzwungen, wobei standardmäßig Gerätenummer 8 verwendet wird,oder jene, auf die sich dar letzte Disk-Befehl bezog.

Diese Systemvariable speichert immer nur den Letztstand einer Fehlerkanalmeldung und erneute Zugriffe auf diese Variable liefern lediglich den damals gelesenen Status ohne den Fehlerkanal tatsächlich erneut abzufragen. D.h. die Variable erfährt nur dann eine Änderung, wenn der Fehlerkanal ausgelesen wird (und damit auch automatisch die Variable DS, deren Wert von der ersten Komponente direkt abgeleitet ist). Ausgelöst wird der Fehlerkanalzugriff, wenn ein entsprechender Befehl in Erwartung einer Floppy-Meldung den alten DS$-Wert verwirft. Bei den von außen ausgelösten Ereignissen, wie etwa einem Hardware-Reset eines Laufwerks bleibt DS$ unangetastet.
Ein gezieltes Auslesen des Fehlerkanals für ein Gerät mit einer bestimmten Gerätenummer ist nur auf Umwegen und unter BASIC 7.0 möglich (siehe Beispiele).

Auswirkung von Ein-/Ausgabe-Befehlen[Bearbeiten]

Befehl ab BASIC-Version Setzen der Gerätenummer Neuauslesen des Fehlerkanals Bemerkung
APPEND 7.0 X X
BACKUP 3.5 X X
BLOAD 7.0 X X
BOOT 7.0 X X
BSAVE 7.0 X X
CATALOG 7.0 X X
CLOSE 2 X nur bei Geräten des seriellen Busses
CMD 2 X nur bei Geräten des seriellen Busses
COLLECT 3.5 X X
CONCAT 7.0 X X
COPY 3.5 X X
DCLOSE 7.0 X X
DIRECTORY 3.5 X X
DLOAD 3.5 X X
DOPEN 7.0 X X
DSAVE 3.5 X X
DVERIFY 7.0 X X
GET 2 kein Einfluss
GET# 2 X nur bei Geräten des seriellen Busses
HEADER 3.5 X X
INPUT 2 kein Einfluss
INPUT# 2 X nur bei Geräten des seriellen Busses
LOAD 2 X
OPEN 2 X nur bei Geräten des seriellen Busses
PRINT 2 kein Einfluss, es sei denn, die Ausgaben ist via CMD auf ein Geräten des seriellen Busses gelegt
PRINT# 2 X nur bei Geräten des seriellen Busses
RENAME 3.5 X X
RUN 7.0 X X
SAVE 2 X
SCRATCH 3.5 X X
VERIFY 2 X

Wie man sieht, wird die auszulesende Geräteadresse nur durch die neuen, ab BASIC 3.5 eingeführten Diskettenbefehle beeinflusst. Die "klassischen" Ein-/Ausgabebefehle aus BASIC 2 hingegen bewirken zwar auch das Neuauslesen des Fehlerkanals und damit das Aktualisieren von DS$, allerdings wird dabei nicht die zuletzt verwendete Gerätenummer gesetzt. Wurde beispielsweise eine Datei mit DOPEN auf Laufwerk 9 geöffnet und anschließend in eine Datei mit klassischen Befehlen auf Laufwerk 8 geschrieben, so liefert DS$ den aktuellen Disk-Status von Laufwerk 9! (siehe Beispiele)
Vorsicht geboten ist auch beim Befehl DCLOSE: Dieser setzt die zuletzt verwendete Gerätenummer für DS$ bzw. DS auf 8 bzw. auf die durch den Parameter U angegebene Nummer, unabhängig davon auf welchem Laufwerk die zu schließende Datei tatsächlich liegt.
Möchte man daher wirklich sicher gehen den aktuellen Fehlerstatus des gewünschten Laufwerks auszulesen (speziell nach BASIC 2 Befehlen), dann kann man sich des DCLOSE-Befehls bedienen, so wie in einem Beispiel beschrieben.

Implementierung[Bearbeiten]

Intern wird DS$ durch einen speziell verwalteten 40 Zeichen langen String repräsentiert, dessen String-Descriptor in der Zeropage liegt. Beim BASIC 7.0 eines C128 befindet sich der String-Descriptor an Adresse $7A, während dessen bei der C264-Serie mit BASIC 3.5 dieser bei Adresse $79 liegt. Dabei befindet sich der String mit der Meldung, nicht in einem reservierten Bereich, sondern gewöhnlich auf dem String-Heap. Aus diesem Grund wäre ein erzwungenes Lesen des Fehlerkanals durch Setzen der String-Länge im Descriptor auf 0 mit der Nebenwirkung behaftet, dass der "alte" String nicht mehr durch die Garbage Collection frei gegeben werden kann.

Beispiele[Bearbeiten]

BASIC V2 Äquivalent[Bearbeiten]

100 OPEN 1,8,15
110 INPUT#1,EC$,EM$,ET$,ES$
120 DS$=EC$+", "+EM$+","+ET$+","+ES$ 
130 CLOSE 1

Floppy-Befehl[Bearbeiten]

100 SCRATCH (FI$)
110 PRINT "LOESCHERGEBNIS: " DS$

Das SCRATCH-Kommando läuft im Grunde parallel zum Programm, d.h. das BASIC-Programm wartet nicht auf die Beendigung des Floppy-Befehls. Erst mit der expliziten Abfrage auf DS, wird das Programm gezwungen, die Beendigung des SCRATCH-Befehls abzuwarten. Die Tracknummer dient bei SCRATCH dann dazu, anzuzeigen, wie viele Dateien tatsächlich gelöscht wurden.

Fehlerkanal gezielt auslesen[Bearbeiten]

Den Fehlerkanal eines bestimmten Geräts, z.B. für Gerätenummer 9 auslesen (nur für BASIC 7.0):

DCLOSE#255,U9
PRINT DS$

Mit "U9" wird das Gerät selektiert, der Befehl selbst verwirft einen eventuell vorher bestehenden Wert für DS$, wobei angenommen wird, dass die logische Dateinummer 255 nicht verwendet wird. Der Fehlerkanal selbst wird durch die Operation nicht beeinflusst.

Unter BASIC 3.5 für Plus/4, C16, C116 gelingt die Festlegung der Gerätenummer, ohne Beeinflussung des Fehlerkanals nur durch direkten Systemzugriff, was die Sache aber ziemlich unportabel macht:

POKE 631,9: REM LAUFWERKSNUMMER AUF 9 SETZEN
OPEN 255,8,15: CLOSE 255: REM GERÄTENUMMER IST HIER EGAL
PRINT DS$

Der POKE-Befehl setzt die Gerätenummer, mit der OPEN-CLOSE-Sequenz wird der letzte DS$-Wert verworfen.

BASIC V2 Anomalie[Bearbeiten]

Wir gehen vom Vorhandensein zweier Geräten (mit Gerätenummer 8 und 9) aus. Zuerst wird mit neuen Disk-Befehlen das Gerät 9 angesprochen, dann mit "alten" Befehlen das Gerät 8:

COPY "A" TO "A-NEU" ON U9
OPEN 1,8,15,"S:XYZ"
PRINT DS$
CLOSE 1
00, OK,00,00

Hier wird lediglich der Fehlerstatus von Gerät 9 wieder gegeben, obgleich ein OPEN an sich das Neueinlesen des Diskettenstatus erzwingen würde. Problem ist aber, dass die zuletzt verwendetet Gerätenummer durch die klassische Ein-/Ausgabe-Befehle nicht gesetzt wird!

Trick bzw. Umgehung durch Verwendung von DCLOSE:

COPY "A" TO "A-NEU" ON U9
DCLOSE #255,U8
OPEN 1,8,15,"S:XYZ"
PRINT DS$
CLOSE 1
00, SCRATCHED, 00,00