← ST-Computer 08 / 1987

Floppyspielereien Teil 2

Kurs

Eine Vielzahl von Themen erwartet Sie in der zweiten Folge unseres Floppy-Kurses. Neben Informationen zu Directory und Bootsektor gibt es zwei Listings sowie Hinweise fĂŒr einen Kopierschutz.

Vorab noch einige Anmerkungen zu HYPERFORMAT, dem Formatierprogramm aus der letzten ST. Mir ist zu Ohren gekommen, daß es vereinzelt Schwierigkeiten mit dem Beschreiben HYPERFORMATierter Disketten gab. Diese Probleme gibt es offenbar dann, wenn zwei Bedingungen Zusammentreffen:

  1. Das Laufwerk dreht zu schnell, oder
  2. Laufwerk und/oder Controller stammen aus einer alten Bauserie des ST.

Mein Verdacht ist also, daß es mehrere Bauserien des Controllers gibt. Sollten Sie einer von den Pechvögeln sein, könnten Sie - wenn Sie sich das Zutrauen und keine GarantieansprĂŒche mehr haben - Ihren ST öffnen und mal nachsehen, welche genaue Bezeichnung Ihr Floppy-Controller hat, das ist der Chip, der ’WD1772’ heißt. Schreiben Sie bitte mir oder dieser Zeitschrift und geben Sie diese Bezeichnung mit an. Ich arbeite daran, auch die Ă€ltesten Bauserien noch glĂŒcklich zu machen.

HĂ€ufig stellt sich offenbar auch die Frage, ob das HYPERFORMAT kompatibel zum AMIGA-Format sei. Zwar haben beide Formate die gleiche Anzahl von Sektoren pro Tracks, zudem verwenden beide das sogenannte MFM-Verfahren zur physikalischen Aufzeichnung. Doch leider leistet sich der AMIGA (wie bei Commodore ĂŒblich) einen eigenen Standard, was das Format der einzelnen Sektoren selbst angeht. Zum GlĂŒck ist der Floppy-Controller des AMIGA sehr flexibel, da er hauptsĂ€chlich softwaregetrieben ist. Und so arbeite ich bereits an einem Programm fĂŒr den AMIGA, das ihm ST-Disketten verstĂ€ndlich macht.

Und fĂŒr diejenigen, die meinem Formatierprogramm nicht so recht trauen, habe ich auch noch ein Schmankerl, nĂ€mlich Listing 1. Dort finden Sie CHKDISK, ein Programm, das Disketten auf Lesefehler untersucht. Es ist nicht nur fĂŒr HYPERFORMATierte Disketten brauchbar. Beim Start meldet es sich mit einem MenĂŒ. Mit ’t’ können Sie die Anzahl der Spuren verĂ€ndern, die geprĂŒft werden sollen, mit ’s’ die Anzahl der Seiten und mit ’p’ die Zahl der Sektoren pro Spur. ’C’ bricht das Programm jederzeit ab, mit RETURN wird es gestartet. WĂ€hrend des Checkvorgangs gibt das Programm den aktuellen Track aus. Wenn ein Fehler auf der Diskette ist, meldet sich CHKDISK mit einem Piepsen und einer Fehlermeldung mit genauer Angabe, wo der Fehler aufgetreten ist. Bei CHKDISK zeigt sich der Vorteil von FTYPERFORMATierten Disketten am deutlichsten: Lassen Sie mal eine HYPERFORMATierte Diskette checken und dann eine normale, und messen Sie jeweils die Zeit, die dafĂŒr benötigt wird!

Am besten, Sie setzen sich gleich mal vor Ihren Rechner und laden Ihren besten Diskmonitor, von denen es ja mittlerweile genug public domain gibt (zum Beispiel auch auf PD-Disketten der ST). Ich gehe davon aus, daß Ihr Diskmon zumindest Sektoren lesen, schreiben und in ASCII und Hexadezimal anzeigen kann sowie eine wenigstens minimale Editierfunktion hat. Sollten Sie keinen solchen Monitor, aber zumindest GfA-Basic haben, können Sie auch das Listing 2 abtippen -dann haben Sie einen kleinen Diskmonitor mit den erwĂ€hnten FĂ€higkeiten.

Formatieren Sie zunĂ€chst eine freie Diskette auf einseitiges Normalformat. Dazu mĂŒssen Sie Laufwerk A einmal anklicken und dann 'formatiere’ im DATEI-MenĂŒ wĂ€hlen. Geben Sie dabei als Diskettennamen ’GRUMMEL. TST’ an.

In der letzten Folge hatte ich bereits erwĂ€hnt, daß die Directory, das Inhaltsverzeichnis der Diskette, beim einseitigen Normalformat bei Track 1, Sektor 3 beginnt. Darin stehen der Diskettenname (wenn angegeben) und die Namen aller Dateien, die Sie darauf abspeichern, mitsamt einigen wichtigen Informationen. So, ist das Laufwerk fertig? Dann starten Sie jetzt Ihren Diskmonitor, legen Sie die formatierte Diskette ein und lesen Sie Track 1, Sektor 3 ein (siehe Anleitung Ihres Diskmons). Es sollte Ă€hnlich Verwirrendes erscheinen wie das hier:

47 52 55 4D 4D 45 4C 20 54 53 54 08 00 00 00 00 GRUMMEL TST...... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .................

In den ersten 32 Bytes der Directory steht jetzt der Eintrag fĂŒr den Diskettennamen. Die ersten 11 Bytes sind fĂŒr den Namen und die Extension reserviert. Filenamen unter 8 Bytes werden mit ZwischenrĂ€umen erweitert, der Punkt wird nicht dargestellt, danach folgt die dreistellige Extension. Was die LĂ€nge der Dateinamen angeht, ist TOS ja - wie MS-DOS - recht geizig. Wenn man da an die Filenamen des AMIGA denkt... Die amputierten Dateinamen haben immerhin den Vorteil, daß das Verzeichnis kompakter wird und damit schneller zu laden ist: und wer will schon eine so einschlĂ€fernde Directory-Leseroutine wie beim AMIGA?

Bitnr. Bit = 1 Bit = 0 Anmerkungen
0 nur Lesen möglich Lesen und Schreiben erlaubt per 'Disk Info' im Desktop zu erreichen
1 'Hidden file' kein 'hidden file' Listschutz fĂŒr das Verzeichnis
2 Systemdatei normale Datei Systemdateien werden auch nicht gelistet
3 Name ist Diskettenname Name ist Dateiname siehe Text oben
4 Datei ist ein Ordner Datei ist kein Ordner siehe Text unten
5 Datei wurde ordnungsgemĂ€ĂŸ bearbeitet 'Archive-Bit', vor allem fĂŒr den Backup bei der Festplatte

Abb. 1

(Bytenummer) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 52 4F 4E 4E 49 45 20 20 55 53 41 00 00 00 00 00 BONNIE USA 00 00 00 00 00 00 86 03 46 oc 02 00 98 13 00 16 17 IS 19 20 21 22 23 24 25 26 27 28 29 30 31

Abb. 2

Wenn Sie genau nachzĂ€hlen, haben wir noch nicht alle Bytes besprochen, in denen etwas steht. Im zwölften Byte steht ’08’. Dies ist das Dateikennzeichen und gibt in diesem Fall an, daß ’GRUMMEL.TST’ der Name der Diskette ist. In das Dateikennzeichen sind folgende Informationen kodiert:

MS-DOS kennt genau das gleiche Dateikennzeichen, sogar die Bitnummern stimmen ĂŒberein. Wieder sieht man, daß die TOS-Entwickler auf der Diskettenebene sehr bemĂŒht waren, sich an den IBM-Standard zu halten.

BITGESTEUERTE TARNKAPPEN UND ANDERE MAGIE

NatĂŒrlich sind Kombinationen der Bits möglich. Sie könnten also einen sichtgeschĂŒtzten Ordner anlegen, der nicht beschreibbar ist, indem Sie das Dateikennzeichen auf $13 Ă€ndern - in der Theorie. Praktisch scheinen hier noch ein paar Unsauberkeiten von TOS verborgen zu sein. Experimentieren Sie ruhig ein wenig mit Ihrem Diskmonitor herum.

Kopieren Sie nun irgendeine Datei auf die leere Diskette und schauen Sie mit dem Diskmon im Verzeichnis (Track 1, Sektor 3) nach. Nehmen wir einmal an, die Datei hieße ’RONNIE.USA’. Dann bekĂ€men Sie etwa folgendes Bild:

Byte 11 zeigt uns, daß RONNIE.USA eine ganz normale Datei ist. Die restlichen Bytes in dieser Zeile bedeuten schlicht & einfach nichts. Ein Directoryeintrag ist nun aber 32 und nicht 16 Bytes lang. Was ATARI in den Bytes der zweiten HĂ€lfte versteckt hat, ist schnell erklĂ€rt:

Byte Inhalt
22-23 Uhrzeit der letzten Änderung
24-25 Datum
26-27 Erster Datencluster der Datei
28-31 GrĂ¶ĂŸe der Datei (Langwort)

Alle diese Bytepaare sind im 8086-Format abgespeichert (niedrigstwertiges Byte zuerst). Man muß sie also erst einmal umdrehen. Sehen wir uns das Datum von RONNIE.USA in den Bytes 22-23 an: Wir drehen ’86 03’ um und erhalten ’03 86’. AufgeschlĂŒsselt in Bits:

0000 0 011 100 0 0110 (0 3 8 6) Stunden—Minuten—Sekunden/2

Also in diesem Fall: 0 Uhr (0000 0), 24 Minuten (011100), 12 Sekunden (00110). FĂŒr das Datum von RONNIE.USA gilt Ă€hnliches:

0000 110 0 010 0 0110 (0 C 4 6) Jahr seit—Monat—Tag—1980

Was bedeutet, daß ich RONNIE.USA am 6.2.1986 gespeichert habe - aber das heißt auch nur, daß in meinem ST keine Echtzeituhr eingebaut ist, denn TOS setzt als Standardwert genau diesen Tag ein.

Bytes 26-27 geben an, bei welchem Cluster (das sind zwei aufeinanderfolgende logische Sektoren) die Datei beginnt. Auch diese Bytes muß man erst krĂ€ftig aufmischen, ebenso wie die darauffolgenden Bytes fĂŒr die GrĂ¶ĂŸenangabe der Datei - waschechtes 8086-Format.

VON PHANTOMEN, FRÖSCHEN UND PRINZEN

Sollten Sie auf der Reise durch diverse Verzeichnisse einmal einen Phantomeintrag entdecken, der im Directoryfenster des Desktops nicht zu finden ist, dann ist das wahrscheinlich ein Eintrag, der mit dem Byte ’E5’ beginnt. ’E5’ heißt: Dieses File ist gelöscht. Nun kommen Sie mir ja nicht mit der Idee, Sie brĂ€uchten nur dieses Byte zu Ă€ndern, und schon hĂ€tten Sie eine bereits abgetakelte Datei ins Leben zurĂŒckgekĂŒĂŸt. Dieser Frosch wird dadurch nĂ€mlich nicht zum schönen Prinzen ( = intakte Datei), es sei denn, die Datei ist höchstens ein Cluster (1024 Bytes) lang. Denn im Directoryeintrag steht nur ein Zeiger auf den ersten Cluster der Datei in der FAT (siehe letzte Folge) - der Rest der Verkettung wird in der FAT gelöscht, wenn Sie einen Prinzen, Verzeihung: eine Datei in die WĂŒste schicken.

Tun Sie jetzt mal etwas ganz Verwegenes: Legen Sie die GRUMMEL-Diskette ein, löschen sie alle Dateien auf ihr und klicken Sie im Desktop 'Neuer Ordner’ an. Nennen Sie ihn, wie Sie gerade lustig sind, also zum Beispiel LUSTIG.FLD (FLD fĂŒr englisch FOLDER = Ordner). Entern Sie ihren Diskmonitor und lesen Sie den Directorysektor. Sie erhalten folgendes:

< Bytenummer 1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 4C 55 53 54 49 47 20 20 46 4C 44 10 00 00 00 00 LUSTIG FLD 00 00 00 00 00 00 55 04 46 0C 02 00 00 00 00 00 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

Abb. 3

Byte 11 (Dateikennzeichen) sagt uns: LUSTIG.FLD ist ein Ordner. Alle restlichen Informationen sind die gleichen wie bei normalen Dateien, nur zeigen Byte 26 und 27 nicht auf den ersten Datencluster der Datei, sondern auf den ersten Cluster des Unterverzeichnisses (Subdirectory). Folgen wir diesem Hinweis: 'Cluster 2’ ist der erste von TOS vergebene Cluster ĂŒberhaupt und beginnt bei einseitigen Disketten auf Spur 2, Sektor 1. Lesen wir diesen Sektor ein...

2E 20 20 20 20 20 20 20 20 20 20 10 00 00 00 00 . 00 00 00 00 00 00 04 55 0C 46 02 00 00 00 00 00 . . 2E 2E 20 20 20 20 20 20 20 20 20 10 00 00 00 00 . 00 00 00 00 00 00 04 55 0C 46 00 00 00 00 00 00 . .

Abb.4

Es werden also in diesem Unterverzeichnis gleich zwei EintrĂ€ge angelegt: Eine fiktive Datei mit Namen und eine mit Namen Diese beiden No-bodies sind nur dazu da, um TOS im Wirrwarr der Unterverzeichnisse die Orientierung zu erleichtern. (beziehungsweise das Clusterbyte dieses Eintrags) zeigt auf das Unterverzeichnis selbst, so daß TOS nicht immer den ganzen Baum von Verzeichnissen lesen muß, um herauszufinden, wo die aktuelle Directory beginnt. zeigt auf die „Vater“directory, die hier angeblich bei Cluster 0 beginnt - das Zeichen dafĂŒr, daß die Vaterdirectory das oberste, das Wurzelverzeichnis ist.

ICH TARZAN - DU JANE

Mit Hilfe dieser speziellen EintrÀge schwingt sich TOS (Tarzan Operating System) an Zeigerlianen durch den Dateidschungel:

Die ’..'-EintrĂ€ge zeigen jeweils auf das ĂŒbergeordnete Verzeichnis, die ’.'-EintrĂ€ge praktisch auf sich selbst.

Innerhalb eines Unterverzeichnisses können beliebig viele weitere Unter-Verzeichnisse angelegt werden - das heißt, fast. Wenn mehr als 40 Unterverzeichnisse auf einer Diskette sind, stĂŒrzt Ihnen Ihr TOS ab: Wenn Sie eine Diskette einlegen und das Verzeichnis einiesen, merkt sich TOS alle Di-rectories in einer speziellen Liste.

Nur ist der Platz fĂŒr diese Liste leider beschrĂ€nkt - mehr als 40 Verzeichnisse passen nicht rein.

Bei Disketten ist das nicht weiter tragisch, aber Festplattenbesitzer haben daran schwer zu knabbern - auf 20 Megabyte sind schnell 40 Directories erzeugt. Zum GlĂŒck gibt es korrigierte ROMs zu kaufen, und gerĂŒchteweise habe ich auch davon gehört, daß die ROMs in den Mega-STs diesen Fehler nicht mehr aufweisen werden.

Alle diese kleinen Details der Diskettenverwaltung gibt es so oder ganz Ă€hnlich sowohl in MS-DOS wie in UNIX - und daher auch das viele Gerede ĂŒber die KompatibilitĂ€t (ein fĂŒrchterliches Wort) von MS-DOS und TOS. Wahr ist: Auf Diskettenebene verstehen sich MS-DOS und TOS ganz gut. Aber sonst werden Sie sich schön umschauen, wenn Sie eine PC-Datei auf einem ST zu starten versuchen.

MÜNCHHAUSEN UND DER ST

Nun zu einem weiteren rĂ€tselhaften Bereich auf der Diskette, dem Bootsektor. Der Bootsektor ist der erste Sektor auf der Diskette und wird bei jedem Diskettenwechsel ĂŒberprĂŒft. Er enthĂ€lt wichtige Daten ĂŒber das Format einer Diskette, kann aber auch selbst ein kleines Programm enthalten, das automatisch ausgefĂŒhrt wird und das System hochbootet - er ist also der Haarschopf, an dem sich der Rechner selbst aus dem Sumpf zieht. Deshalb reagiert Ihr ST auch ziemlich heftig, wenn er so einen Bootsektor nicht lesen kann - hĂŒten Sie also Ihre Systemdisketten wie Ihr Glasauge, machen Sie am besten eine Kopie auf eine hochwertige Diskette, schließen Sie sie weg, geschĂŒtzt vor KinderhĂ€nden, Hundeschnauzen, Kaffeetassen, Erdbeben, Feuer, Wasserrohrbruch und grĂ¶ĂŸeren intergalaktischen Katastrophen.

Es gibt zwei Typen von Bootsektoren: ausfĂŒhrbare und nicht ausfĂŒhrbare. Erstere werden fĂŒr Systemdisketten verwendet, von denen das TOS gebootet wird. AusfĂŒhrbare Bootsektoren werden vom Betriebssystem so abgeĂ€ndert, daß ihre Checksumme (das heißt, die auf 16 Bit reduzierte Summe ihrer Bytes) gleich $ 1234 ist. Trifft das zu, versucht TOS, ein Programm im Bootsektor auszufĂŒhren.

Gemeinsam ist allen Bootsektoren folgender Aufbau: (Byte - ErklÀrung)

0-1
Verzweigungsbefehl auf Bootprogramm (wenn ausfĂŒhrbar)

2-7
’Loader’

8-10
24Bit-Seriennummer

11-12
BPS: Bytes pro Sektor (normal 512)

13
SPC: Sektoren pro Datencluster (normal 2)

14-15
RES: reservierte Sektoren (normal 1)

16
FAT: Anzahl der FATs (normal 2) 17-18

DIR: Anzahl der EintrÀge in der Directory (normal 112)

19-20
SEC: Anzahl der Sektoren auf der Diskette

21
MEDIA: „Media-Descriptor-Byte“

22-23
SPF: Sektoren pro FAT

24-25
SPT: Sektoren pro Track

26-27
SIDE: Anzahl der Seiten (SF354:1 SF314:2)

28-29
HID: versteckte Sektoren 510-511

Ausgleichswerte fĂŒr die Checksumme (Differenz der Checksumme ĂŒber die voranstehenden Bytes und $1234)

Alle 16-Bit-Worte sind wieder im 8086/ INTEL-Format abgesichert (also niedrigstwertiges Byte zuerst). Bei ausfĂŒhrbaren Bootsektoren sind weitere Bytes interessant:

30
EXEC: Ist das Flag gesetzt, wird versucht, nach dem Betriebssystem gleich COMMAND.PRG zu finden und zu starten (ohne Umweg ĂŒber das DeskTop)

32
MODE: Ist MODE Null, wird das File FNAME gesucht. Wenn nicht, ist man im „Sektormodus“: Es werden einzelne Sektoren geladen (siehe SCNT und START)

34
START: erster Sektor, der bei MODE= 1 geladen werden soll

36
SCNT: Anzahl der Sektoren, die bei MODE=l geladen werden sollen

38
ADDR: Speicheradresse, wohin das Bootfile oder die Sektoren geladen werden sollen

42
Speicheradresse, wohin FATs und Directory geladen werden sollen

46
FNAME: Filename bei MODE=0 (maximal 11 Zeichen)

58
Anfang des Bootprogramms

Alle diese Flags werde ich Ihnen ganz bestimmt nicht vorkauen, sonst paßt in dieses Heft höchstens noch das Vorwort hinein. Aber einige interessante Stellen werden wir uns schon ansehen.

Besorgen Sie sich zunĂ€chst einmal einen ausfĂŒhrbaren Bootsektor. Sie haben doch sicher noch eine bootfĂ€hige Systemdiskette? Wenn nicht, formatieren Sie eine Diskette mit HYPERFORMAT und geben Sie dabei an, daß sie ausfĂŒhrbar sein soll. HYPERFORMAT erzeugt dann einen ausfĂŒhrbaren Bootsektor auf Track 0, Sektor 1. Lesen Sie mit Ihrem Diskmonitor den Bootsektor ein und Ă€ndern Sie EXEC (Byte 30, hexadezimal $1E) von Null auf Eins. Jetzt mĂŒssen Sie noch in den Ausgleichsbytes eine Eins abziehen, damit die Checksumme wieder stimmt. Schreiben Sie diesen modifizierten Sektor auf Ihre Diskette zurĂŒck und kopieren Sie auf diese Diskette ein TOS. IMG, ein DESKTOP.INF und ein COMMAND.PRG. DrĂŒcken Sie den Reset-Knopf, und Sie werden sehen, daß COMMAND.PRG noch vor dem Desktop ausgefĂŒhrt wird.

Das kann man dazu verwenden, komplizierte BootvorgĂ€nge auszufĂŒhren. Denn wenn COMMAND.PRG startet, sucht es auf der Diskette eine Batchdatei namens AUTOEXEC.BAT und fĂŒhrt sie aus, falls vorhanden. Wenn Sie sich also so eine Diskette zurechtgezimmert haben, brauchen Sie wirklich nur noch den Netzschalter, um Ihr System hochzufahren, wie Sie es wollen - beispielsweise mit installierter, gefĂŒllter RAM-Disk, sauber gefĂŒhrtem Logbuch und einer fertigen Anwendung. Allerdings macht TOS beim Ausstieg aus COMMAND.PRG per ’exit’ noch Arger. Ich nehme an, daß das an nicht initialisierten GEM-Vektoren liegt - vielleicht hat sich ja schon ein Leser damit herumgeschlagen und kann darĂŒber berichten.

Sie ahnen bestimmt, welche Tricks mit dem Bootsektor möglich sind. Andern Sie doch mal FNAME von TOS. IMG nach UNIX.IMG, ebenso den Namen von TOS.IMG auf Ihrer Bootdiskette und verblĂŒffen damit Ihre Freunde! Oder gaukeln Sie Ihrem Rechner vor, das Laufwerk hĂ€tte 3 Seiten, 150 Spuren oder 0 Sektoren pro Track. KĂŒrzen Sie die Anzahl der FATs oder deren GrĂ¶ĂŸe (vielleicht auch die der Directory) und gewinnen so Speicher auf der Diskette. Allerdings mĂŒssen Sie bei allen Änderungen auf einem ausfĂŒhrbaren Bootsektor immer die Checksumme ausgleichen, indem Sie die letzten beiden Bytes des Bootsektor abĂ€ndern!

Das sollte Ansporn genug sein, sich mit dem Bootsektor zu beschĂ€ftigen. Es sei noch angemerkt, daß Sie natĂŒrlich nicht gezwungen sind, vom Bootsektor immer nur TOS.IMG zu laden...

Sollten Sie im Verlauf des Artikels bisher nicht alle Details verstanden haben, machen Sie sich keine großen Sorgen: Daran erkennt man die besonders nachdenklichen Menschen. Probieren Sie ein bißchen mit Ihrem Diskmonitor herum, kopieren oder löschen Sie Dateien, formatieren Sie mal normal, mal mit HYPERFORMAT, schnippeln Sie am Bootsektor herum und schauen Sie sich die Ergebnisse an. Kurz: Spielen Sie (das kann man auch ohne Joystick)! Was Sie dabei lernen, ist die Zeit sicher wert.

Wenn Sie beim Spielen einmal TOS-Fehlernummern bekommen (solche, die per Alert-Box im Desktop angezeigt werden), dann sind das bestimmt die Fehlernummern 33 und 35. Andere Nummern werden nicht angezeigt, obwohl TOS mehr Fehler unterscheidet. Das liegt an einem Fehler gerade in jener Routine des TOS, die die Fehler erkennen soll - ist das nicht tragisch? Man kann nur hoffen, daß ATARI bei den Mega-ST-Roms auch an diesen Fehler denkt.

Überhaupt gibt es allerlei Fehler in den ROMs. Bei dieser Gelegenheit möchte ich die wichtigsten, die mir aufgefallen sind, erwĂ€hnen:

  1. Die Laderoutinen sind Ă€ußerst langsam. Das liegt daran, daß TOS vor jedem Lesevorgang lieber zweimal nachprĂŒft, ob der Lesekopf auch wirklich ĂŒber der richtigen Spur liegt - was aber ziemlich unnötig ist. FAST-ROMs beheben diesen Fehler beim ROM-TOS, FASTLOAD und HYPERFORMAT beim RAM-TOS.
  2. Zuweilen kommt es vor, daß man ein Dokument auf dem Desktop anklickt und es sich auf dem Schirm anzeigen lassen will. Unter bestimmten (ungeklĂ€rten) UmstĂ€nden stĂŒrzt TOS selbst bei dieser primitiven Routine ab (2-10000 Bomben)!
  3. Dialoge, die Fehler haben, deren Eingabemaske (alpha) numerisch definiert wurde, stĂŒrzen ab, wenn man den Unterstrich (_) eingibt.
  4. Fehler bei mehr als 40 Unterverzeichnissen (siehe oben).
  5. Im Desktop lassen sich weder Ordner- noch Diskettennamen Ă€ndern. Das liegt hauptsĂ€chlich daran, daß die zugehörige GEMDOS-Funktion RENAME ($56) keine solchen speziellen Dateien umnennen kann. Zwar ist im Aufruf ein Dummywort vorgesehen, das wahrscheinlich gerade zur Unterscheidung der Dateitypen dienen sollte, doch bewirkt es nichts.
  6. Fehler in der Fehlerroutine (siehe oben).
  7. Wenn man sich das Desktop mal in Zeitlupe anschaut, erkennt man, daß Window-Elemente oft mehrere Male gezeichnet, gelöscht und wieder gezeichnet werden. Darunter leidet die Geschwindigkeit.
  8. Unsauberkeiten beim Dateikennzeichen (siehe oben).

Wenn Sie weitere Fehler entdeckt haben, melden Sie sich! Wenn erst genug Fehler bekannt werden, nimmt sich ATARI vielleicht ein Flerz und killt die Bugs im ROM der Mega-STs.

Im letzten Teil dieser Folge möchte ich ein bißchen theoretischen Untergrund aufbauen, damit wir demnĂ€chst selbst einen Kopierschutz auf Disketten erzeugen können. GrundsĂ€tzlich einmal: Kopierschutz basiert immer darauf, den Disketten Eigenschaften mitzugeben, die Kopierprogramme nicht erwarten und deswegen nicht richtig ĂŒbertragen können. Das jeweilige Programm fragt dann nach dem Starten auf diese besondere Eigenschaft ab. Flat die Diskette diese herstellerbedingte Macke, ist alles in Ordnung, das Programm hat einen ehrlichen Anwender vor sich. Fehlt der gewisse Tick, verabschiedet sich das Programm je nach Temperament des Programmierers mit einem bloßen ’Un-authorized Copy - Byebye’ oder mit frisch-fröhlichem Formatieren der Diskette, wobei sich proportional zur Reaktion des Programms das Gesicht des ĂŒblen Kopierers verfinstert.

Zur Erinnerung noch einmal die Grobstruktur einer Diskette: 80 Spuren sind jeweils in mehrere Sektoren (normalerweise 9) eingeteilt. Daraus ergibt sich bereits die erste Idee fĂŒr einen Kopierschutz: Im Bootsektor gibt man an, daß auf jeder Spur nur 9 Sektoren sind, in Wirklichkeit aber formatiert man die Spuren auf 10 Sektoren. Ein argloses Kopierprogramm kopiert friedlich 9 Sektoren und vergißt den jeweils zehnten, ohne den das Programm nicht lauffĂ€hig ist.

Allerdings gibt es kaum noch ein Kopierprogramm, das auf einen solch simplen Trick noch hereinfĂ€llt. Eine verfeinerte Version dieses Kopierschutzes arbeitet mit variabler Sektoranzahl, das heißt, mal 5, dann 8, schließlich 10 Sektoren, wild durcheinander. Da muß ein Kopierprogramm schon schlauer sein und erst einmal vor dem Lesen jede Spur genau analysieren. Aber auch das ist bereits Standard.

Eine andere Idee: Wie Sie aus der letzten Folge bereits wissen, kann man die Sektoren nicht nur einfach hintereinander auf die Spur formatieren, sondern auch versetzt (Interleave), zum Beispiel so:

S(ektor) 1 S3 S5 S7 S9 S2 S4 S6 S8

Nehmen wir an, wir wollen Sektor 1 bis 9 lesen. Das funktioniert auch ganz prÀchtig. Ein unachtsames Kopierprogramm schreibt aber die Sektoren anders auf die Zieldiskette:

S1 S2 S3 S4 S5 S6 S7 S8 S9

Diesen Unterschied kann ein Programm dadurch herausfinden, indem es die Zeit mißt, die beim Lesen zweier aufeinanderfolgender Sektoren verstreicht - die Ă€ndert sich nĂ€mlich, wenn man am Interleave manipuliert. Nachteil dieses Kopierschutzes: Er kann auch mal ansprechen, wenn ein Laufwerk benutzt wird, das die Drehzahl nicht richtig einhĂ€lt - und so auch ehrlichen Anwendern schaden.

Am gewalttÀtigsten aber sind Kopierschutzmechanismen, die an der Struktur der Sektoren selbst drehen. Zur Erinnerung - ein Sektor sieht beim ST so aus:

Vorspann (Index, Trackheader; "PoST Index Mark”)

(*) LĂŒckenbytes (Pre Adress Mark) Synchronisationsbytes Adressmarke + Sektorinfo Checksumme

LĂŒckenbytes (PoST Adress Mark) Synchronisationsbytes Datenmarke + DATEN Checksumme

LĂŒckenbytes (PoST Data Mark)

zurĂŒck zu (*), bis alle Sektoren geschrieben sind, danach: LĂŒckenbytes bis zum Trackende.

Als Kopierschutz könnte man jetzt die Anzahl der Synchronisations- oder LĂŒckenbytes Ă€ndern. Kopien erkennt man wieder z. B. durch Zeitunterschiede (das ist allerdings sehr knifflig). Mein Formatierprogramm HYPERFORMAT, das Sie aus der letzten ST kennen, ist - wenn Sie so wollen -auch ein Kopierschutz, weil es Ă€hnliches tut, um 11 Sektoren auf einer Spur unterzubringen. Ich kenne nur wenige Kopierprogramme, die HY-PERFORMATierte Disketten korrekt lesen können (das normale Filecopy des Desktop funktioniert dagegen hervorragend!). Deswegen sei an dieser Stelle auch ein Kopierprogramm fĂŒr dieses Format angekĂŒndigt.

Ganz hartnĂ€ckig ist ein Schutz, wenn er im Controller Fehler erzeugt: Sei es, indem man die Checksummen im Sektor manipuliert, sei es durch sogenannte halbe Sektoren, das heißt, man kĂŒndigt dem Controller zwar einen Sektor mit 512 Bytes an, liefert aber nur 200 oder 300. Normalerweise meldet sich der Controller dann mit einem Lesefehler und streikt - und nur sehr gute Kopierprogramme sind dann so schlau und lassen das Laufwerk solange rotieren, bis sie jedes Byte rekonstruiert haben. Hier findet man eigentlich die grĂ¶ĂŸte Vielfalt von Ideen: Man könnte auch Sektoren mit jeweils 1024 Bytes einfĂŒhren, die zwar der Controller lesen kann, aber nur mit speziellen Leseroutinen. Oder man vergißt Datenmarken, das sind Stopschilder fĂŒr den Controller, an denen er innehĂ€lt und weiß: Hoppla, jetzt kommen Daten.

So, jetzt habe ich Ihnen aber den Mund lange genug wĂ€ĂŸrig gemacht. Diese Folge hat Ihnen gezeigt, wie Sie mit Directory und Bootsektor umspringen können. Sie haben jetzt ein Diskcheck-Programm, einen kleinen Diskmonitor in GfA-Basic, den wir schrittweise erweitern werden, sind jetzt vielleicht etwas aufmerksamer, was TOS-Fehler angeht und wissen -zumindest vom Prinzip her - wie ein Kopierschutz funktioniert. In der nĂ€chsten St werden wir uns daran machen, selbst einen Kopierschutz zu entwerfen. Wenn Sie ganz tief einsteigen wollen, dann halten Sie bis dahin Assembler-Kenntnisse bereit. Aber keine Angst: FĂŒr die Nur-Basic-Programmierer gibt es eine Einbindung der benötigten Routinen in BASIC. Keep hacking!

In den Untergrund

Tiefer in das Reich des Lesekopf können Sie mit dem MINIMON tauchen. Er ist in GfA-Basic verfaßt und besteht aus zwei Teilen, dem Sektormonitor und dem Trackmonitor. Der Trackmonitor ist noch nicht implementiert. Wir werden ihn im Laufe der Zeit vervollstĂ€ndigen, wenn wir im Kurs neue Tricks besprechen. Nach dem Start hat man die Auswahl zwischen Sektormonitor (S), Trackmonitor (T) und Quit (Q). Der Sektormonitor bietet folgende Funktionen:

Track einstellen: (’T’)
Eingabe der Spurnummer (bei mehr als 80 wird’s gefĂ€hrlich fĂŒr den Lesekopf Ihrer Floppy).

Seite einstellen: (’S’)
Vorder- oder RĂŒckseite (0/1). Jede andere Nummer ist sinnlos, die 1 ohnehin nur fĂŒr Besitzer doppelseitiger Laufwerke brauchbar.

Sektor einstellen: (’K’)
Sektornummer eingeben. Sinnvoll sind bei normalen Format 1-9, bei FAT-DISK und Àhnlichen Formaten 1 -10, bei HYPERFORMAT 1-11.

Read sector: (’R’)
Den vorher mit ’T’, ’S’, ’K’ eingestellten Sektor in einen Puffer im Speicher einiesen.

Write sector: (’W’)
Den Pufferinhalt an die mit ’T’, ’S’ und ’K’ eingestellte Stelle schreiben.

Dump sector: (’D’)
Den Pufferinhalt ausgeben. Eine Zeile sieht so aus: [Bytenr] [16 Bytes] [ASCII]. Mit SPACE kann man die Ausgabe anhalten, mit irgendeiner anderen Taste abbrechen.

Edit: (’E')
Ein Byte im Puffer Ă€ndern. MINI-MON fragt zunĂ€chst nach der Nummer des Bytes (mit DUMP zu erfahren), dann nach dem neuen Inhalt des Bytes. Sie können den neuen Wert als Zahl eingeben oder (in ’ - Zeichen eingeschlossen) als ASCII-Zeichen.

Printer: (’P’)
Schaltet Druckerausgabe ein/aus.

Execute: (’X’)
Anderes Programm ausfĂŒhren. Zeigt das Verzeichnis an und erlaubt, ein anderes Programm zu starten, von dem aus man wieder zum Minimon zurĂŒckkehren kann. Diese Funktion können Sie auch benutzen, um nur ein Verzeichnis auf den Schirm zu bringen. Sollten Sie am Directorysektor etwas geĂ€ndert haben, empfiehlt es sich, vor ’X’ die Diskette kurz herauszuziehen und wieder einzusetzen.

Quit: (’Q')
Raus aus dem Sektormonitor.

Bei Lese- und SchreibvorgÀngen ermittelt MINIMON den Status des Laufwerks und zeigt ihn in der Statuszeile an.

Zum Programm selbst:

Am interessantesten' ist wohl der Betriebssystemaufruf in der Prozedur Lesen:

Status% = Xbios(8,L:Buffer%,L:0, Drive%, Sector%, Track%,Seite%,l)

Hier wird das XBIOS des ST aufgerufen und ihm verschiedene Parameter ĂŒbergeben. ’8’ ist die Nummer der Leseroutine im XBIOS. ’L:Buffer%’ gibt die Adresse eines Puffers im Speicher an, wohin XBIOS den Sektorinhalt einiesen soll. ’L:’ ist GfA-spezifisch und erzwingt die ParameterĂŒbergabe als Langwort. Fehlt ’L:’, nimmt GfA-BASIC an, daß der Parameter WortgrĂ¶ĂŸe haben soll. Nach Buffer% folgt ein (noch) vom Betriebssystem unbenutztes Langwort, sodann die Angabe des Laufwerks (hier voreingestellt mit 0 fĂŒr Laufwerk A; Laufwerk B ist dann 1, C entspricht 2 usw.). Es folgen Sektor, Track, Seite und eine ominöse 1: Es soll nur ein Sektor eingelesen werden. Der Systemaufruf in der Prozedur Schreiben ist bis auf die Funktionsnummer identisch.

Wichtig: In der ST lief ja bereits eine Serie ĂŒber das Betriebssystem, wo alle Parameter bei den Aufrufen angegeben waren. FĂŒr GfA-Basic ist anzumerken, daß alle Parameter hier (wie in C) in umgekehrter Reihenfolge hinzuschreiben sind; in Assembler steht die Funktionsnummer als letztes, in Basic als erstes.

***************** * CHKDISK * Testet eine Diskette in Laufwerk A * (auch HYPERFORMATiert) * auf fehlerhafte Sektoren * * Written 1987 by Claus Brod * Version 1.0, last update 23.5.1987 * **************** start: move.l a7,a5 * Speicherplatz reservieren move.l 4(a5),a5 move.l $c(a5),d0 add.l $14(a5),d0 add.l Slc(a5),d0 add.l #$500,d0 * stack move.l d0,d1 add.l a5,d1 and.l #-2,d1 * gerade machen move.l d1,a7 move.l d0,-(sp) move.l a5,-(sp) clr.w -(sp) move.w #$4a,-(sp) trap #1 add.l #12,sp ****************** * Hauptschleife ****************** lea header(pc),a2 * BegrĂŒssung bsr printmsg * ausgeben bsr parameter ■ Parametereingabe bsr main * Ab ins Hauptprogramm exitus: * Sense clr.w -(sp) trap #1 ******************* * PrĂŒfschleife ******************* main: move.w #0,a4 * Aktueller Track move.w #1,a5 * Aktueller Sektor move.w #0,d6 * Aktuelle Seite ***************** * Sektor lesen ***************** readsec: move.w #1,-(sp) * nur 1 Sektor lesen move.w d6,-(sp) * Seite move.w a4,-(sp) * Track move.w a5,-(sp) * Sektor move.w #0,-(sp) * Laufwerk A clr.l -(sp) move.l #buffer,-(sp) * Pufferadresse move.w #8,-(sp) * Sektor lesen trap #14 * XBIOS add.l #20,sp tst.b d0 * Fehler passiert? bne fehler * ja, zur Fehlerroutine next: addq.w #1,a5 * NĂ€chster Sektor cmp.w spt(pc),a5 * letzter Sektor? bls readsec move.w #1,a5 * Sektor 1 lea sides(pc),a2 cmp.b #1,(a2) * 1 oder 2 Seiten beq nexttrack * nur eine Seite sor.w #1,d6 * Seite wechseln bne readsec * schon auf 0 gewechselt? nein, lesen nexttrack: bsr printtrack * Tracknummer ausgeben addq.w #1,a4 * nĂ€chster Track cmp.w end(pc),a4 * schon alle Tracks? bne readsec * nein, lesen rts ***************** * Fehlerroutine ***************** fehler: lea s_error(pc),a2 * Fehlernummer ausgeben bsr mkhex lea m_error(pc),a2 * Fehlerstring ausgeben bsr printmsg move.w a4,d0 * Track ausgeben lea s_track(pc),a2 * String fĂŒr Track bsr mkhex * Hexzahl schreiben lea m_track(pc),a2 bsr printmsg move.w a5,d0 * Sektor ausgeben lea s_sec(pc),a2 bsr mkhex lea m_sec(pc),a2 bsr printmsg move.w d6,d0 * Seite ausgeben lea s_side(pc),a2 bsr mkhex lea m_side(pc),a2 bsr printmsg bra next * nĂ€chster Sektor ****************** * String ausgeben ****************** printmsg: * String ausgeben (in: A2) move.l a2,-(sp) * Adresse des Strings move.w #9,-(sp) trap #1 addq.l #6,sp rts ****************** * Track ausgeben ****************** printtrack: * Tracknummer ausgeben move.l a4,d0 lea s_akt(pc),a2 bsr mkhex lea m_akt(pc),a2 bsr printmsg rts ***************** * D0 nach hexadezimal wandeln ***************** mkhex: * Hexzahl erzeugen (in:DO) move.l #1,d1 * Nur ein Byte nochnbyte: clr.l d2 move.l d0,d2 asr.l #4,d0 * Ein Nibble weiterschieben and.l #$0f,d2 * ausmaskieren cmp.b #9,d2 * Zahl oder Buchstabe? bis zahl add.b #7,d2 * 7 addieren (Buchstabe) zahl: add.b #48,d2 * 48 addieren move.b d2,0(a2,d1) * Ergebnis schreiben dbf d1,nochnbyte * weiteres Byte wandeln? rts ******************* * auf Taste warten ******************* getkey: * auf Taste warten (con in move.w #7,-(sp) * without echo) trap #1 addq.l #2,sp rts ********************* * Parameter-MenĂŒ ausgeben und * auf Eingaben warten ********************* parameter: * auf Eingabe von neuen Parametern lea m_end(pc),a2 * warten bsr printmsg bsr getkey * auf Taste warten cmp.b #3,d0 * C? beq exitus * ja, raus cmp.b #13,d0 * RETURN? beq fertig * ja, mit Check anfangen cmp.b #'s',d0 * Seitenanzahl beq op_sides * Ă€ndern cmp.b #'S',d0 beq op_sides cmp.b #'t',d0 * Trackanzahl beq op_tracks * Ă€ndern cmp.b #'T',d0 beq op_tracks cmp.b #'p',d0 * Sektorenanzahl beq op_spt * Ă€ndern cmp.b #'P',d0 beq op_spt bra parameter fertig: rts ******************* * Seitenzahl Ă€ndern ******************* op_sides: * Anzahl der Seiten Ă€ndern lea sides(pc),a2 lea s_seiten(pc),a3 eor.b #3,(a2) eor.b #3,1(a3) bra parameter ******************* * Trackzahl Ă€ndern ******************* op_tracks: * Anzahl der Tracks Ă€ndern lea end(pc),a2 lea s_end(pc),a3 move.b 1(a2),d0 move.b 1(a3),d1 addq.b #1,d1 addq.b #1,d0 cmp.b #85,d0 * mehr als 85 sind nicht bis trackok * drin move.b #80,d0 * Startwert move.b #'0',d1 trackok: move.b d0,1(a2) move.b d1,1(a3) bra parameter ******************** * Sektoren pro Track Ă€ndern ******************** op_spt: * Anzahl der Sektoren pro lea spt(pc),a3 * Track Ă€ndern lea s_spt(pc),a2 move.b 1(a3),d0 addq.b #1,d0 cmp.b #11,d0 bis sptok move.b #1,d0 sptok: move.b d0,1(a3) bsr mkhex bra parameter .even * Fehlermeldung m_error: .dc.b 7,'Fehler ' s_error: .dc.b '00',13,10,0 m_track: .dc.b ' bei Track: ' s_track: .dc.b '00',13,10,0 m_sec: .dc.b ' Sektor:' s_sec: .dc.b '00',13,10,0 m_side: .dc.b ' Seite: ’ s_side: .dc.b '00',13,10,13,10,0 .even * BegrĂŒĂŸung header: .dc.b 27,’E',27,'pDISKCHECK’,27,'q',13,10 .dc.b 'Written 1987 by Claus Brod' .dc.b 13,10,0 m_end: .dc.b 27,'Y',32+5,32+0,27,'pT',27,'qracks: ' s_end: .dc.b '83',13,10 m_seiten: .dc.b 27,'pS',27,'qeiten: ' s_selten: dc.b '02',13,10 m_spt: .dc.b 'Sektoren ',27,'pp',27,’qro Track: $' s_spt: .dc.b '0B',13,10 .dc.b 13,10,'RETURN Check starten',13,10 .dc.b 'CTRL-C Abbrechen',13,10,0 m_akt: .dc.b 27,'j',27,’Y’,32+0,32+65,'Track: ' s_akt: .dc.b '00',27,'k',0 end: .dc.w 83 spt: .dc.w 11 sides: .dc.b 2 .bss buffer: * Sektorpuffer .ds.b 512

Listing 1: Source Code

' Minimon fĂŒr den ST ' Written 1987 by Claus Brod ' Am Felsenkeller 2 ' 8772 Marktheidenfeld ' Cls Do Print Print "Minimon ST - (C) 1987 by Claus Brod" Print Repeat Print "Sektormonitor oder Trackmonitor oder Quit (S/T/Q)?" A$=Upper$(Input$(1)) Until A$="S" Or A$="T" Or A$="Q" Exit If A$ = "Q" If A$ = "S" @Sektormon Else @Trackmon Endif Loop End ' ' Procedure Gibmirzeit Alert 1,"Funktion noch nicht|implementiert.",l,"OK",A Return ' ' Das Modul Trackmon wird im Laufe des Kurses noch ' vervollstĂ€ndigt ' Procedure Trackmon @Gibmirzeit Return ' ' Sektormon: Kleiner Diskmon mit StandardfĂ€higkeiten ' Procedure Sektormon Cls Prn%=0 Status%=0 Seite%=0 Track%=0 Sector%=1 Drive%=0 Sec$=Space$(5i2) R$=Chr$(27) + "p" O$=Chr$(27) + "q" @Lesen Do Print Print "....... Minimon (C) 1987 Claus Brod Status: ";Status%;........" Print R$;"R";OS:"ead, ";R$;"W";OS;"rite, ";R$;"T";O$;"rk (";Track%;"), "; Print R$;"S";0$;"eite (";Seite%;"), Se";R$;"k";OS;"tor (";Sector%;"), "; Print R$;"E";0$;"dit, ";R$;"D";O$;"ump, ";R$:"P";0$;"rn (o"; If Prn% Print "n), "; Else Print "ff), "; Endif Print "E";RS;"x";O$;"ec, ";R$;"Q";O$;"uit” M$ = Upper$(Input$(1)) If M$ = "X" @Exe Endif If M$="P" Prn%=1-Prn% Endif If M$ = "T" Input "Track";Track% Endif If M$ = "S" Input "Seite";Seite% Endif If M$ = "K" Input "Sektor";Sector% Endif If M$ = "R" @Lesen Endif If M$ = "W" @Schreiben Endif If M$ = "E" @Edit Endif If M$ = "D" @Dump Endif Exit If M$ = "Q" Loop Return ' ' Sektor einlesen ' Procedure Lesen Buffer%=Varptr(Sec$) Status%=Xbios(8,L:Buffer%,L:0,Drive%,Sector%,Track%,Seite%,1) Return ' ' ' Sektor schreiben ' Procedure Schreiben Buffer%=Varptr(Sec$) Status%=Xbios(9,L:Buffer%,L:0,Drive%,Sector%,Track%.Seite%,1) Return ' ' Sektorpuffer ausgeben ' Procedure Dump If Prn%=0 Open "O",#1,"con:" Else Open "O",#1,"prn:" Endif Print #1,"Track: ";Track%;" Sektor: ";Sector%;" Seite: ";Seite% For T=1 To 512 Step 16 A$=Str$(T-1) While Len(A$)<3 A$="0"+A$ Wend D$ = " " Print #1,A$;D$; For I=0 To 15 V$=Mid$(Sec$,T+1,1) A$ = Hex$(Asc(V$)) If V$<" " Or V$>"z" V$="." Endif Print #1,Right$("0"+A$,2)' DS=D$+V$ Next I Print #1,D$ A$=Inkey$ If A$ = " " A=Inp(2) Endif Exit If A$>"" And A$<>" " Next T Close #1 Return ' ' Byte Ă€ndern ' Procedure Edit Input "Byte Nr.";Byte% Print "Alter Wert ist: ";Asc(Mid$(Sec$,Byte%+1,1)) Input "Neuer Wert in dezimal oder ASCII";Wert$ Wert%=Val(Wert$) If Wert%=0 And Left$(Wert$,1)<>"0" Wert%=Asc(Wert$) Endif Mid$(Sec$,Byte%+1,1)=Chr$(Wert%) Return ' ' ' anderes Programm ausfĂŒhren ' Procedure Exe Fileselect "*.*","",Sel$ If Exist(Sel$)<>0 S=Fre(0) Reserve 50000 Showm Exec 0,Sel$,"","" Reserve S-1000 Endif Return

Listing 2: Diskmonitor in GFA-Basic

Claus Brod