Wie der ST seine Disketten verwaltet, und wie man ihm dabei gehörig auf die Sprünge helfen kann, soll hier am Beispiel eines Programmes gezeigt werden, das Träume erfüllt: Der HYPERFORMATTER bläst Disketten bis auf schwindelerregende 927000 Bytes auf und beschleunigt dazu noch den Zugriff um bis zu 30 %
927000 Bytes?! Wie macht man das? Um das zu erklären, muß ich weiter ausholen, weil mein Programm viele Finessen verwendet, die erst mal erklärt werden wollen. Ich möchte Ihnen dazu in einem Blitzkurs in zwei Folgen Grundlegendes und Raffiniertes über Disketten und Laufwerke erzählen. Sie sollten auch schon mal eine Diskette in der Hand gehabt haben — das sid diese kleinen viereckigen Dinger, die immer dem Bürostuhl unter die Rolle kommen (knirsch) — und Bits von Bytes unterscheiden können, sonst wird dieser Kurs Ihnen wohl nicht so viel bringen. Aber zumindest können Sie die Programmbeispiele abtippen und sich an den Ergebnissen delektieren.
Beginnen wir zur Abwechslung mal am Anfang: TOS, das Betriebssystem des ST (also nicht dieser Grafikaufsatz namens GEM), hält sich in der Diskettenverwaltung recht sklavisch an Vorgaben des großen Bruders MS-DOS. Grundsätzlich: Eine Disk teilt sich ein in Spuren (Tracks) und Sektoren. Bei der SF354 sind es 80 Tracks, bei der SF314 sogar 2 x 80 Tracks, weil da die Disketten beidseitig beschrieben werden. Jeder Track besteht wiederum aus 9 Sektoren:
Spur 79 liegt innen, Spur 0 außen. Zwischen den Sektoren gibt es kleine Lücken, auf die ich noch zu sprechen komme. In den Sektoren werden die eigentlichen Daten abgespeichert, beim ST 12 Bytes pro Sektor.
Über der rotierenden Diskette schwebt ein Schreib-Lesekopf. Beim Schreiben fließt Strom durch den Schreibkopf und erzeugt eine magnetische Fährte auf der Diskette. Beim Lesen ist es umgekehrt: Die magnetisierten Partikel auf der Disk induzieren einen Stromfluß im Lesekopf, den er als logisch T oder ’0‘ versteht. Aber keine Angst: So tief in die Physik brauchen wir nicht einzusteigen, der ST verfügt über einen Baustein (nämlich einen Diskcontroller), der sich um diese Dinge kümmert. Dieser Baustein im ST ist auch der Grund, warum die Programme dieses Kurses auch auf Fremdlaufwerken laufen: Die Floppystationen am ST sind nicht wie die anderen Rechner (C64) intelligent, sondern bestehen fast nur aus Mechanik.
Das bedeutet, die Ansteuerung hängt nur vom Controller ab, und der ist ja bei allen ST-Rechnern gleich.
Nun sieht man schon auf der Zeichnung, daß nach dem neunten Sektor noch viiiiel Platz ist, so viel Platz, daß viele Formatierprogramme (zum Beispiel) auch FAT-DISK aus der ST/86) dort einen zehnten Sektor unterbringen und so die Kapazität erhöhen. Das macht pr Spur immerhin 312 Bytes aus, bei 80 Spuren und 2 Seiten sind das 80 Kilobyte!
Bei vielen Laufwerken kann man auch den Schreib-Lesekopf bis über Track 79 hinaus bewegen. Einer eigenen Blitzumfrage bei Händlern und ST-Besitzern zufolge gibt es allerdings bei etwa der Hälfte aller Laufwerke Probleme ab Track 82, weil der Lesekopf anschlägt. Um herauszufinden, ob Ihr Laufwerk auch Track 82 noch mitmacht, sollten Sie mal eine freie Disk mit FATDISK formatieren. Legen Sie das Ohr aufs Laufwerk (ja, ich weiß, es klingt lächerlich, aber es lohnt sich) — wenn es bei Track 82 (FATDISK zeigt den aktuellen Track an) anders klingt als bei den vorherigen Trackwechseln (es hört sich etwa so an, als ob ein kleines Männchen in der Floppy den Lesekopf mit einem Hämmerchen bearbeitet), haben Sie Pech: Tyrannisieren Sie irgendjemanden, der Ihnen Ihre Floppy einstellen kann. Vielleicht kann der ja noch was machen. Andererseits können einige Leute aber auch ihren Kopf (quatsch, den ihrer Floppystation) bis Spur 85 bewegen!
Ein wenig Arithmetik: 83 Spuren (also Spur 0 bis Spur 82) mal 10 Sektoren mal 2 Seiten macht 1660 Sektoren = 849920 Bytes. Von dieser Summe geht aber noch einiges für Bürokratie weg, bei FATDISK bleiben nur 828416 Bytes übrig.
Da ist zum ersten der geheimnisumwitterte Bootsektor (Track 0, Sektor 1, Seite 0), der 512 Bytes frißt. Nach dem Einschalten prüft der ST den Bootsektor der Diskette in Laufwerk A. Wenn dieser Bootsektor ausführbar ist, versucht der ST von dieser Diskette ein TOS zu laden. Außerdem stehen noch viele andere Informationen im Bootsektor, die ich genauer in der zweiten Folge behandeln werde.
Ab dem zweiten Sektor steht die sogenannte FAT (File Alloction Table). Auf ihr ist die Belegung der Diskette mit Dateien vermekrt. Das Format ist allerdings a bisserl kompliziert. Vorweg: TOS verwaltet seine Disketten nicht in logischen Sektoren, sondern in Clustern. Das sind jeweils 2 aufeinanderfolgende Sektoren. Eine neue Datei belegt mindestens einen ganzen Cluster — selbst bei einer Datei mit nur einem Byte! Diese Verschwendungssucht schmiert aber den Verwaltungsmechanismus und beschleunigt die Bürokratie (Parallelen mit der ,wirklichen“ Welt sind rein zufällig). Eine typische FAT fängt nun so an:
Jeder Cluster erhält in der FAT 12 Bit (!) zugewiesen, das sind drei Flexadezimalzt/ fern. Die ersten 5 Nullen sind Flags, deren Bedeutung ich noch nicht vollständig entschlüsselt habe. Bei MS-DOS, dem großen Bruder, steht im ersten Byte ein Format-kennzeichen, im zweiten ist die Kapazität der Floppy eingetragen. Seltsamerweise beeindrucken Änderungen der ersten beiden Bytes TOS nicht sonderlich.
Vielleicht hat sich ja schon ein Leser damit befaßt und scheibt mir oder der ST. Das :bere Nibble des 3.Bytes bedeutet offenbar auch nichts Besonderes (wie gesagt, ich bin für Tips zugänglich). Aber dann folgt cer Eintrag des Clusters mit der Nummer 2 (TOS speichert Daten erst ab Cluster 2 ab). Hier sehen wir ’003‘, das heißt: Die Datei, die im Cluster 2 beginnt, wird im Cluster 3 fortgesetzt. Im Eintrag für Cluster 3 steht ’400‘, also ein umgedrehtes ’004‘ (warum auch immer), die Datei setzt sich folglich bei Cluster 4 fort undsoweiter.
Am Schluß der Datei steht ein Endekennzeichen (FFO). In MS-DOS zumindest gibt es noch die Kennzeichen FF7 (Sektor beschädigt) und FF8—FFF (Dateiende). Für jeden Cluster sind 12 Bit reserviert, macht (bei normalen Format) 8640 Bit = 1080 Byte, also knapp 3 Sektoren. Trotzdem reserviert ATARI großzügig 5 Sektoren für die FAT.
Direkt auf die erste FAT folgt eine identische Kopie der FAT, aus Sicherheitsgründen. Nett gedacht, nur: beide FATs liegen in der Regel auf der gleichen Spur, und da viele Programme gleich eine ganze Spur schreiben, segelt bei einem Fehlgriff auch die Kopie ins Nirwana. Traurig, traurig, denn nur mit diesem roten Faden (oder besser: FATen) kann man feststellen, welche Bereiche eine Datei belegt. Gerade bei zerstörten Dateien ist das sehr wichtig — und ohne FAT gleicht der Versuch, die Datei wieder zusammenzuklauben, einer stecknadelsuche im Vesuv.
Ein Tip für diejenigen, die es trotzdem versuchen wollen (oder müssen, mein Beileid): TOS versucht grundsätzlich, aufeinanderfolgende Sektoren für neue Dateien zu verwenden. Erst wenn es auf einen breits belegten Sektor stößt, weicht das Betriebssystem aus. Auf einer einigermaßen leeren Diskette hat man also noch relativ gute Chancen, seine Dateisektoren wiederzufinden.
Nach den FATs steht in 7 Sektoren die Directory, beim normalen Format ab dem 12. Sektor, vom Anfang der Diskette an gezählt (dabei zählt man zuerst die Sektoren der Vorderseite, dsann die der Rückseite, so vorhanden, und geht dann weiter zum nächsten Track). Jeweils 32 Bytes pro Datei beinhalten deren Namen und Kenndaten unter anderem auch einen Verweis auf den ersten Dateicluster. Damit gerüstet, schaut TOS an der betreffenden stelle der FAT nach und kann den Verlauf einer Datei verfolgen. Genaueres zur Directory im Teil 2 der Reise durchs wilde Floppy-stan (in der nächsten ST).
Kurze Überschlagsrechnung: Für die Verwaltung einer Diskette gehen summa summarum 18 Sektoren für Bootsektor, FATs und Direcotry hops, also 9216 Bytes.
Nochmal in der Zusammenfassung der Anfang einer ST-Diskette:
1. Sektor: Bootsektor (Track 0, Seite 0, Sektor 1)
2. Sektor: FAT1 (Track 0, Seite 0, Sektor 2)
7. Sektor: FAT2 (Track 0, Seite 0, Sektor 7)
12. Sektor: Directory (bei SF314: Track 0, Seite 1, Sektor 3? bei SF 354: Track 1, Seite 0, Sektor 3)
Danach: Daten und Programme
Manche Formatierprogramme kürzen die beiden FATs noch auf jeweils 3 Sektoren (was völlig ausreicht) und die Directory auf 64 Einträge (also 4 Sektoren) und gewinnen so 7 Sektoren = 2584 Bytes.
Trotzdem, das alles kann noch nicht das Wahre sein: der AMIGA hat doch auch diseiben Laufwerke und formatiert auf 880K. Warum kann das der ST nicht, fragt man sich. Er kann. Aber dazu mußte ich erst mal einiges umbiegen.
Glücklicher AMIGA, du hast es leichter. Das Betriebssystem des AMIGA formatiert nämlich eine Diskette mit 11 Sektoren pro Spur! Macht zusammen — bei 80 Spuren — über 900000 Bytes! Et voila, dachte ich mir, ds müßte der ST doch auch können, setzte mich fröhlich pfeifend an meinen ATARI-Ferrari, um die Sache auszuprobieren, und verlor schon nach kurzer Zeit die Lust: Ein schnell zusammengehacktes Formatierprogramm für 11 Sektoren formatierte zwar, doch überschrieb der elfte Sektor immer den ersten: Zuwenig Platz auf der Spur. Was tun? Irgendwo im Betriebssystem entdeckte ich schließlich die Formatierroute des XBIOS, die man auch über den internen XBIOS-Aufruf 10 erreicht. Wenn man analysiert, was TOS da so auf die Diskette schreibt, kommt man schließlich auf folgendes Track-Format: (siehe Tabelle 1)
Das Problem: Es paßt zuwenig auf eine Spur, um einen elften Sektor schreiben zu können. Die Beobachtung: Zwischen den einzelnen Informationen auf der Spur liegen immer wieder Lückenbytes (Gapbytes). Schlußfolgerung: Wenn man die Lücken auf ein Minimum kürzt, bringt das vielleicht so viel Platz auf der Spur, daß noch ein elfter Sektor draufpaßt.
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.
(Tabelle 1: Einer Spur auf der Spur)
Und in der Tat: Man kann die Lückenbytes kürzen (durch Änderungen in der Formatierroutine des TOS), wenn man sich nur daran hält, daß mindestens 30 Lückenbytes zwischen Adreßmarke und Daten geschrieben werden. Das erste HYPERFORMAT modifiziert also zuerst mein RAM-TOS so, daß 11 Sektoren auf eine Spur passten, rief dann ganz normal das XBIOS auf, um zu formatieren, und gab dabei an, 11 Sektoren formatieren zu wollen.
HYPERFORMATiert man eine Diskette nach diesem Verfahren, gibt es allerdings bald lange Gesichter:
1. Nicht jedes Laufwerk vertrug offenbar die Roßkur fürs XBIOS. Auf Laufwerken von Freunden ließen sich HYPERFORMATierte Disketten zunächst nicht lesen, später zwar lesen, aber nicht HYPER-FORMATieren. Nach kniefieslingster Probiererei mit den Lückengrößen scheinen auch andere Laufwerke mein HYPERFORMAT zu verstehen, so daß ich damit an die Öffentlichkeit treten kann, ohne sofortige Enthauptung zu fürchten. Sollte es doch nicht laufen, liegt das an physikalischen Toleranzen der Laufwerke.
2. Die Schreib-Lesegeschwindigkeit zwar zunächst ein Graus (3mal langsamer, als die sowieso nicht sehr schnelle SF314 sonst liest). Ein Freund kam auf die rettende Idee — Stichwort Interleave (dafür bekam er auch eine Widmung im Programm).
Normalerweise werden die Sektoren so auf die Spur geschrieben wie in Bild 1 angegeben, also erst Sektor 1, dann Sektor 2 und sofort. Beim normalen Format liest die Floppy zuerst den Sektor 1, der Floppycontroller (das ist der Baustein, der die Ansteüerung des Laufwerks übernimmt) werkelt jetzt ein bißchen, und wenn er wieder bereit ist, hat sich die Lücke zwischen den Sektoren gerade unterm Lesekopf vorbeigedreht, so daß gleich der nächste Sektor gelesen werden kann. Bei den gekürzten Lücken stimmt nun dieses Timing nicht mehr, und der Controller muß immer wieder Pausen einlegen und warten, bis der passende Sektor wieder unter dem Lesekopf vorbeirotiert. Nun kann man eine Spur aber auch so formatieren:
Damit hat der Controller zwischen zwei aufeinanderfolgenden Sektoren (etwa zwischen Sl und S2) immer genug Zeit! Diese Taktik nennt man Interleaving, der Interleavefaktor ist in diesem Falle — und auch per Voreinstellung in meinem Programm — sechs (weil auf die aktuelle Sektornummer immer sechs addiert wird; wenn das Ergebnis größer als die Anzahl der Sektoren pro Spur ist, wird diese Anzahl abgezogen). So modifiziert, bringt HYPERFORMAT eine Diskette auf beachtliche Geschwindigkeit: Im Durchschnitt ist sie im gemischten Schreib-Lesezugriff 20 bis 35 % schneller als normal formatierte Disketten, in Einzelfällen liegt dieser Wert sogar noch weit besser.
Dieser Geschwindigkeitsvorteil rührt auch daher, daß man beim Diskzugriff nicht mehr so oft den Track wechseln muß, weil mehr Daten auf eine Spur passen. Und der Trackwechsel ist auch eine zeitaufwendige Sace (normalerweise werden jeweils 3ms dafür verbraten).
3. In der bisherigen Version lief HYPERFORMAT nur auf RAM-TOS, da ja Passagen aus dem TOS geändert, gepatcht werden mußten. In der jetzigen Version ist auch das gelöst.
HYPERFORMAT prüft nach, ob ein ROM-TOS vorliegt, wenn nein, erwartet es ein RAM-TOS in der Version vom 6.2.86 im Speicher (es müßte auch mit der Version vom 18.7.85 laufen), wenn ja, benutzt es eine modifizierte ROM-Routine mit Einsprüngen ins ROM. Eine wichtige Anmerkung: Booten Sie ein FASTLOAD mit, wenn Sie den Geschwindigkeitsvorteil von HYPERFORMAT-Disketten nutzen wollen. Beim Umschreiben des Programmes auf ROM-Rechner habe ich bemerkt, daß das Timing beim Lesen und Schreiben nur mit FASTLOAD optimal ist. Deswegen installiert HYPERFORMAT bei gebootetem RAM-TOS gleich FASTLOAD und FASTFORMAT mit.
ROM-Beisitzer haben zwei Möglichkeiten: Ein FASTLOAD-Programm booten (in den AUTO-Ordner kopieren), das auch auf ROM-Rechnem läuft, oder die ROMs in Eproms kopieren und dabei auf den FASTLOAD-Modus umbrennen. Dazu ändert man im Eprom U7 den Inhalt der Eprom-Adresse $0DC7 von $14 auf $10 (modifizierte EPROMS gibt es auch für 30 Mark zu kaufen). Eine von diesen Möglichkeiten sollten Sie nutzen, um alle Vorteile von HYPERFORMAT genießen zu können. Die FASTLOAD-Modifikation läuft übrigens schon seit einem Jahr bei mir und bei vielen Bekannten ohne Kompliaktionen, also keine falsche Vorsicht.
Und ein kleines Trostpflaster für ST-Besitzer ohne FASTLOAD: Das Formatieren läuft bei HYPERFORMAT auch bei ROM-Rechnern mit derselben Geschwindigkeit, als wäre ein FASTLOAD mitgebootet worden! Und wenn Sie den Interleavefaktor auf 3 einstellen, ergibt sich sogar doch noch ein kleiner Geschwindigkeitsvorteil gegenüber normalen Disketten.
Allerdings werden Disketten mit Interleavefaktor 3 wieder langsam, wenn man sie mit FASTLOAD liest. Deswegen empfehle ich dringend (um auch vom Speed her die Kompatibilität zu wahren), den Interleave nicht zu verstellen, sondern ein FASTLOAD ins TOS zu integrieren.
Das Programm ist vollständig in Assembler geschrieben und relokatibel; es wurde mit dem AS68 aus dem Entwicklungspaket assembliert. Andere Assembler brauchen eventuell andere Pseudo-Ops; bitte halten Sie sich an die Anleitung Ihres Assemblers. Das Programm an sich ist recht lang zum Abtippen, seien Sie vorsichtig. Die Kommentare müssen Sie ja nicht treudoof runterhacken, aber lesen Sie die Hinweise, man kann dabei sicher was für die eigene Programmierung lernen. Nicht zuletzt deswegen ist HYPERFORMAT heavily documented, wie der Angelsachse so schön sagt.
Wenn Sie das Programm fertig eingetippt ich beneide Sie nicht), assembliert (fluch!) und gelingt (bibber!) haben, dann starten und keine Bomben oder ATARI-Gardinen entdecken, haben Sie es geschafft, Sie sind im Menü angekommen.
Im Menü können Sie einige Parameter einstellen, zum Beispiel, wieviel Spuren Sie formatieren wollen (wichtig für Leute mit dem Knackatakatak bei der 82. Spur), wieviel Seiten Ihr Laufwerk hat (auf der einseitigen Floppy hat man dank HYPERFORMAT 459000 Bytes frei), wieviel Directoryeinträge Sie zulassen wollen, und welcher Interleavefaktor gewählt wird.
Voreingestellt sind 2 Seiten, 83 Tracks (also Spur 0 bis Spur 82 einschließlich), 64 Directoryeinträge und ein Interleavefaktor 6, und damit ergeben sich mehr als 927000 freie Bytes auf Ihrer Diskette (AMIGA go home!). HYPERFORMAT kürzt die FATs dabei auf völlig ausreichende drei Sektoren. CTRL-C im Menü bricht das Programm ab, RETURN startet das Formatieren, ’B‘ überspringt das Formatieren und schreibt nur Bootsektor, FAT und Directory neu. ROM-Besitzer ohne FASTLOAD können den Interleave auf 3 einstellen (siehe oben).
Zusätzlich sind im Listing noch folgende Parameter änderbar:
virgin (Daten, mit denen die Sektoren beim Formatieren initalisiert werden) spt (Sektoren pro Track) res (Reservierte Sektoren) fat (Anzahl der FATs) secsperfat (Länge der FAT)
Von allen anderen Parametern im Listing sollten Sie zunächst mal die Finger lassen.
Sollte Ihr Laufwerk doch mal bocken und Lesefehler melden, können Sie in den Routinen change_tos und rom_fmt die gekennzeichneten „Lücken“ von 3 auf 4 vergrößern, das hilft meistens.
Diesmal haben Sie erfahren, wie eine Diskette aufgebaut ist, wie die Aufzeichnung funktioniert, was FATs, Cluster und Diskcontroller sind, wie man mit kleinen Tricks den Verwaltungsaufwand reduzeirt und mehr Platz gewinnt, und Sie haben jetzt mit HYPERFORMAT die ultimate Waffe gegen den Knetefraß durch Diskettenkauf. In der nächsten ST lesen Sie, wie man auf den Diskettencontroller des ST zugreift, was der für Finessen beherrscht, wie man BIOS, XBIOS und GEMDOS für die Arbeit mit der Floppy nutzen kann, wie gängige Kopierschutzmechanismen funktionieren und einiges mehr.
(Tabelle 2: Hier noch eine Liste der Routinen von HYPERFORMAT:
maln Hauptschleife
change_tos modifiziert RAM-TOS und inSTa11iert FASTLOAD+FASTFORMAT repair_tos macht Änderungen am RAM-TOS rückgängig, nicht aber FASTLOAD und FASTFORMAT formatdisk ganze Diskette formatieren formattrack eine Spur formatieren
rom Vorbereitungen für die romfmt-Routine romfmt Modifzierte Formatierroutine aus dem ROM
writeboot Bootsektor und FATs initialisieren
writesector einen Sektor schreiben
printmsg STring ausgeben
waitforkey Auf TaSTe warten
mallocerror,freeerror,fatal-error Fehlermeldungen
Parameters Eingabeschleife fürs Menü
op_exe Exe-Flag ändern
op_tracks Anzahl der Tracks ändern
op_side Anzahl der Seiten einSTellen
op_dir Wieviele Directoryeinträge?
op_inter Interleavefaktor ändern
calc_secs Zahl der Sektoren auf der Disk ausrechnen
*********************************************************
* HYPERFORMATTER *
* Written 1987 by Claus Brod *
* Am Felaenkeller 2 *
* 8772 Marktheidenfeld *
* (C) 1987 and for all eternity by Claus Brod *
* *
* 1. Formatiert Diskette in Laufwerk A *
* auf über 905K (>927000 Bytes frei) *
* 2. Beschleunigt Diskzugriff bei Laden *
* und Speichern um 20-35% *
* *
* Version für RAM- und ROM-TOS *
* Revision 2.0, Last update 4.4.87 *
* Assembliert mit AS68 aus dem Entwicklungspaket *
*********************************************************
virgin .equ $cbcb * Virgin data
spt .equ 11 * Sektoren pro Track
laufwerk .equ 0 * Laufwerk A
secsperfat .equ 3 * Sektoren pro FAT
spc .equ 2 * Sectors per Cluster
res .equ 1 * Reservierte Sektoren
fat .equ 2 * Anzahl der FATs
bufflength .equ 10000 * Länge des Trackpuffers
******************
* Routine zum Reservieren von Speicherplatz
******************
move.l a7,a5 * Stackpointer retten
move.l 4(a5),a5 * Basepage—Start vom Stack nach a5
move.l $c(a5),d0 * Länge von .text
add.l $14(a5),d0 * Länge von .data addieren
add.l $1c(a5),d0 * Länge von .bss addieren
add.l #$500,d0 * Platz für den Stack muß auch sein
move.l d0,d1 * Ergebnis nach d1
add.l a5,d1 * Ergebnis + Adresse der Basepage
and.l #-2,d1 * Adresse gerade machen
move.l d1,a7 * Stackpointer = errechnete Adresse
move.l d0,-(sp) * Größe des Bereiches
move.l a5,-(sp) * Startadresse. ab der reserviert wir
clr.w -(sp) * Dummy (reserviert)
move.w #$4a,-(sp) * SETBLOCK
trap #1 * im GEMDOS
add.l #12,sp
clr.l -(sp) * Userstack wird Supervisorstack
move.w #$20,-(sp) * SUPER
trap #1 * im GEMDOS
add.l #6,sp * ab jetzt alles im Supervisormode
lea save_ssp(pc),a2
move.l d0,(a2) * Supervisorstackpointer retten
cmpi.l #$00FC0000,$4F2 * von ROM gebootet?
beq rom_ist_da * ja. weiter
bsr change_tos * RAM-TOS patchen
lea romflag(pc),a2
move.b #-1,(a2) * Flag für 'kein ROM' setzen
rom_ist_da:
bsr main * Ab ins Hauptprogramm
exitus:
lea romflag(pc),a2
cmpi.b #-1,(a2) * ROM drin?
bne rom_sweet_rom * jawoll, weiter
bsr repair_tos * Heileheilegänschen fürs RAM-TOS
rom_sweet_rom:
move.l save_ssp(pc),-(sp) * zurück
move.w #$20,-(sp) * in den Usermode
trap #1
add.l #6,sp
clr.w -(sp) * Raus in die boese Welt
trap #1
**************************
* main: Holt Parameter, formatiert
* und gibt Gelegenheit zur Wiederholung
**************************
main:
lea msg1(pc),a5 * Intromeldung
bsr printmsg * ausgeben
bsr parameters * Parameter einsteilen
lea diskmsg(pc),a5
bsr printmsg * 'Diskette einlegen'
bsr waitforkey * auf Taste warten
bsr calc_secs * Sektoren ausrechnen
lea fmtflag(pc),a2
cmpi.b #13,(a2) * Formatieren oder nur Bootsektor?
bne nurboot
bsr formatdisk * eigentliche Formatierroutine
nurboot:
lea againmsg(pc),a5 * Noch'ne Message
bsr printmsg
bsr writeboot * Bootsektor etc. schreiben
bsr getkey * auf Taste warten
cmpi.b #'y',d0 * nochmal?
beg main * 'y' für ja, zurück
cmpi.b #'Y',d0
beq main * 'Y' für ja, zurück
rts
**************************
* change_tos: ändert TOS ab
**************************
change_tos:
lea $000075c2,a5 * a5 auf Anfang der fmt-Routine
move.b #3,$81(a5) * Post Index Mark, evt. auf 4
move.b #3,$8f(a5) * Pre Adress Mark. evt auf 4
move.b #21,$bf(a5) * Post Adress Mark 1
move.b #11,$cb(a5) * Post Adress Mark 2 C2)
move.b #3,$f9(a5) * Post Data Mark, evt auf
move.w #600,$118(a5) * Nachspann
move.l #$6000034c,$58fa5) * FASTFORMAT
suba.1 a5,a5 * a5 löschen
move.b #$10,$7a1d(a5) * FASTLOAD
rts
**********************
* repairtos: siehe oben, nur retour
**********************
repair_tos:
lea $000075c2,a5
move.b #$3b,$81(a5)
move.b #$b,$8f(a5)
move.b #$15,$bf(a5)
move.b *$b,$cb(a5)
move.b #$27,$f9(a5)
move.w #$578,$118(a5)
rts
***********************
* formatdisk: von Track 0-endtrack formatieren
***********************
formatdisk:
move.l #bufflength,-(sp) * bufflength Bytes
move.w #$48,-(sp) * per MALLOC
trap #1 * (GEMDOS)
addq.l #6,sp * reservieren
tst.l d0 * Fehler?
bmi mallocerror * Rumpel...
move.l d0,a6 * Trackpufferadresse nach a6
move.w #0,d4 * ab Track 0 formatieren
floop:
move.w #0,d5 * Seite 0 formatieren
bsr formattrack
lea side(pc),a2
cmpi.b #2,(a2) * 1 oder 2 Seiten?
bne nureine * eine Seite, nächster Track
move.w #1,d5 * Seite 1 formatieren
bsr formattrack
nureine:
addq.w #1,d4 * Nächster Track
cmp.b endtrack(pc),d4 * alle Tracks formatiert?
bls floop * Nein, weiter
move.l a6,-(sp) * Reservierten Bereich per
move.w #$49,-(sp) * MFREE im GEMDOS
trap #1 * wieder freigeben
addq.l #6,sp
tst.l d0 * Fehler?
bne freeerror * Da soll doch...
rts
************************
* formattrack: Einen Track formatieren
* d5:Seite, dd:Track, a6:Puffer
***********************
formattrack:
move.w #virgin,-(sp) * Virgin
move.l #$87654321(sp) * Magic Number
move.w ileave(pc),-(sp) * Interleave
move.w d5,-(sp) * Seite
move.w d4,-(sp) * Track
move.w #spt,-(sp) * Sektoren pro Track
move.w #1aufwerk,-(sp) * Laufwerk (A)
clr.l -(sp)
move.l a6,-(sp) * Pufferadresse
lea romflag(pc),a2
move.b (a2),d0
cmp.w #-1,d0 * ROMs eingebaut?
bne rom * ja, in ROM-Routine
move.w #10,-(sp) * Und ab ins XBIOS: flopfmt
trap #14
add.l #2,sp
redo_stk:
add.l #24,sp
tst d0 * Fehler passiert?
bmi fatalerror * Oje oje
rts
rom:
move.l $4a2,a1
movem.l d3-d7/a3-a7,-(a1) * Register retten
move.l a1,$4a2
clr.l a5 * a5 löschen
lea $FC0000,a0 * Offset-Register für ROM-Calls
bsr romfmt
move.l $4a2,al
movem.l (a1)+,d3-d7/a3-a7 * Register holen
move.l a1,$4a2
bra redo_stk
**************************
* romfmt-, modifzierte Formatierroutine des ROM
**************************
romfmt:
jsr $1CBE(a0) * Disketten gewechselt?
moveq.l #$FF,d0
jsr $1A34(a0) * Parameter setzen
lea $fc0000,a0
jsr $1014(a0) * select drive and side
move.w $E(a7),$9D4(a5) * Sektoren pro Track
move.w $14(a7),$9D6(a5) * Interleave
move.w $1A(a7),$9D8(a5) * Virgin
moveq.l #2,d0
lea $fc0000,a0
jsr $1CF6(a0) * Diskette gewechselt
lea $fc0000.a0
jsr $1B28(a0) * Track anfahren
bne fatalerror * Fehler beim Tracksuchen
move.w $9C4(a5),$0(a1) * aktueller Track
move.w #$FFFF.$9E0(a5)
bsr machhin * Track formatieren
bne fatalerror * Fehler passiert
move.w $9D4(a5),$9CA(a5) * Sektoren/Track als Zähler
move.w #1,$9C6(a5) * mit Sektor X anfangen
lea $fc0000,a0
jmp $lada(a0) * flopok (verify überspringen)
machhin:
move.w #$FFF6.$9DE(a5)
move.w #1,d3 * mit Sektor X anfangen
move.l $9cc(a5),a2 * Adresse des Puffers
move.w #3,d1 * 4 Lückenbytes (evt. auf
move.b #$4E,d0 * move.w #4,d1 ändern)
bsr wmult * in Puffer schreiben
nsect2:
move.w d3,d4 * Sektornummer retten
nsect:
move.w #3,d1 * 4 Lückenbytes (evt. auf
clr.b d0 * move.w #4,d1 ändern)
bsr wmult
move.w #2,d1 * 3 Syncbytes (nicht ändern!)
move.b #$F5,d0 * $F5 schreiben
bsr wmult
move.b #$FE,(a2)+ * $FE, Adreßmarke schreiben
move.b $9C5,(a2)+ * Tracknr. schreiben
move.b $9C9,(a2)+ * Seite
move.b d4,(a2)+ * Sektor
move.b #2,(a2)+ * Bytes pro Sektor. Hibyte
move.b #$F7,(a2)+ * Checksumme schreiben
move.w #$15,d1 * 22 Lückenbytes (nicht ändern!)
move.b #$4E,d0 * $4E schreiben
bsr wmult
move.w #$b,d1 * 12 Lückenbytes (nicht ändern!)
clr.b d0 * 0 schreiben
bsr wmult
move.w #2,d1 * 3 Syncbytes (nicht ändern!)
move.b #$F5,d0 * $F5 schreiben
bsr wmult
move.b #$FB,(a2)+ * $FB- Datenblockmarke
move.w #$FF,d1 * 256 Worte
wrvirgin:
move.b $9D0(a5),(a2)+ * Virgin data
move.b $9D9{a5),(a2)+
dbra d1,wrvirgin
move.b #$F7,(a2)+ * Checksum schreiben
move.w #3,d1 * 4 Lückenbytes (evt. auf
move.b #$4E,d0 * move.w #4,d1 ändern)
bsr wmult
**************************
* writeboot: Bootsektor etc. schreiben
**************************
writeboot:
lea bootsector(pc),a5 * Bootsektor-Adresse
move.w executable(pc),-(sp) * Ausfuhrbarkeitsflag
move.w #-1,-(sp) * Disktyp nicht andern
move.l #$11000000,-(sp) * Serial number zufällig erzeugen
move 1 a5,-(3p) * Adresse des Puffers übergeben
move.w #18,-(sp) * PROTOBT
trap #14 * im XBIOS
add.l #14,sp
move.w #0,d5 * Track 0
move.w #1,d6 * Sektor 1
move.w #0,d4 * Seite 0
bsr writesector * Bootsektor schreiben
move.w #2,d6 * Ab Sektor 2
move.w #0,d4 * Beite 0
move.w #0,d5 * Track 0
lea cleansector(pc),a5 * cleansector schreiben
cnochma1:
bsr writesector
addq.w #1,d6
cmp.w #12,d6
bne cnochma1
rts
*******************
* writesector: Einen Sektor schreiben
* Seite in d4, Track in d5, Sektor in d6, Pufferadresse in a5 *******************
writesector:
move.w #1,-(sp) * Count
move.w d4,-(sp) * Seite
move.w d5,-(sp) * Track
move.w d6,-(sp) * Sektor
move.w #laufwerk,-(sp) * Laufwerk
clr.l -(sp) * Füllsel
move.l a5,-(sp) * Pufferadresse
move.w #9,-(sp) * FLOPWR
trap #14 * Xbios
add.l #20,sp
rts
********************
* printmsg: String ausgeben
* Adresse in a5
********************
printmsg:
move.l a5,-(sp) * Message ausgeben
move.w #9,-(sp)
trap #1 * GEMDOS
addq.l #6,sp
rts
add.w $9D6(ab),d4 * Interleave draufzählen
cmp.w $9D4(a5),d4 * mit größter Sektornummer^v
ble nsect * vergleichen
addq.w #1,d3 * Startsektor plus eins
cmp.w $9d6(a5),d3 * Interleave
ble nsect2
move.w #600,d1 * 601 Lückenbytes (Änderung
move.b #$4E,d0 * zwecklos)
bsr wmult
move.b $9CF(a5),$FFFF860D * DMA—Lowbyte
move.b $9CE(a5),SFFFF860B * DMA-Midbyte
move.b $9CD(a5),SFFFF8609 * DMA-Highbyte
move.w #$190,(a6) * DMA-Status säubern
move.w #$90,(a6)
move.w #$190,(a6) * Datenrichtung
move.w #$1F,d7
lea $fc0000,a0
jsr $1C90(a0) * d7 an Controller schicken
move.w #$180,(a6)
move.w #$F0,d7 * format_track-Befehl
lea $fc0000.a0
jsr $1C90(a0) * d7 an Controller
move.l #$40000,d7 * timeout-Zähler
mfploop:
btst #5,$fffffa01 * Controller fertig?
beq dmastatus * ja. weiter
subq.l #1,d7 * nein, warten
bne mfploop
lea $fc0000,a0
jsr $1BFA(a0) * abbrechen
kaputt:
moveq.l #1.d7 * Fehler
rts
dmastatus:
move.w #$190,(a6) * DMA-Status
move.w (a6),d0 * lesen
btst #0,d0 * Fehler?
beq kaputt * ja, Fehler
move.w #$180,(a6)
lea $fc0000,a0
jsr $1CA4(a0) * Register lesen
lea $fc0000,a0
jsr $165A(a0) * Fehlernummer
and.b #$44,d0
rts
wmult: * Bytes in Puffer schreiben
move.b d0,(a2)+
dbra d1,wmu1t
rts
**********************
* waitforkey: 'Taste drücken' ausgeben
* und auf Taste warten
***********************
waitforkey:
lea keymsg(pc).a5 * ‘Taste drücken'
bsr printmsg
getkey: * Einsprungpunkt ohne Message
move.w #7,-(sp) * Auf Taste warten
trap #1 * GEMDOS Conin without echo
addq.l #2,sp
rts
*************************
* Error-Routine mit Einsprungpunkten für verschiedene
* Fehlermeldungen. Gibt Fehler aus und verabschiedet sich
*************************
mallocerror:
lea ma1locmsg(pc),a5 * Fehler beim Reservieren von Speicher
bra error
freeerror:
lea freemsg(pc),a5 * Fehler bei der Freigabe von Speicher
bra error
fata1error:
lea errormsg(pc),a5 * Fehler beim Formatieren
error:
bsr printmsg * Error-Routine. Textadresse in a5
bsr waitforkey * Gibt Message aus, wartet auf Taste
bra exitus * und terminiert
*************************
* Parameters: Gibt Menue aus
* und erlaubt Änderungen
*************************
parameters:
lea msg_parms(pc),a5
bsr printmsg * Menue ausgeben
bsr getkey * Auf Taste warten
cmpi.b #3,d0 * ^C?
beq exitus * ja, raus
cmpi.b #13,d0 * RETURN?
beq end_parms * ja, fertig
cmpi.b #'b',d0 * 'b' für boot
beq end_parms
cmpi.b #'B',d0
beq end_parms
cmpi.b #'d',d0 * 'd' gedrückt
beq op_dir * Dir—Einträge ändern
cmpi.b #'D',d0
beq op_dir
cmpi.b #'s’,d0 * 's' gedrückt
beq op_side * Seitenzahl ändern
cmpi.b #'S',d0
beq op_side
cmpi.b #'t',d0 * 't' gedrückt
beq op_tracks * letzten Track andern
cmpi.b #'T',d0
beq op_tracks
cmpi.b #'e',d0 * 'e' gedrückt
beq op_exe * Ausführbarkeit andern
cmpi.b #'E',d0
beq op_exe
cmpi.b #'i',d0 * 'i' gedrückt
beq op_inter * Interleave ändern
cmpi.b #'I',d0
beq op_inter
bra parameters
end_parms:
lea fmtflag(pc),a2 * fmt oder nur boot
move.b d0,(a2)
rts
op_exe: * Ausführbarkeitsflag ändern
lea s_exe(pc),a2 * Stringadresse
lea executable(pc),a3 * Adresse der Variablen
move.w (a3),d0
move.b #’Y',d1 * Yes als Default
eor.w #1,d0 * Flag invertieren
bne wr_exe * nicht ausführbar?
move.b #'n',d1 * auf 'No' ändern
wr_exe :
move.b d1,(a2) * String und
move.w d0,(a3) * Flag ändern
bra parameters
op_tracks: * Tracks ändern
lea s_tracks(pc),a2 * Stringadresse
lea endtrack(pc),a3 * Adresse der Variablen
move.b $1(a2),d0 * Low-Nibble des Strings
move.b (a3),d1 * Wert
addq.b #1,d1 * um eins erhöhen
addq.b #1,d0
cmpi.b #'7',d0 * mehr als 86 Tracks läuft nicht
bne wr_tracks
move.b #'0',d0
move.b #79,d1 * letzter Track 79
wr_tracks:
move.b d0,$1(a2) * String und
move.b d1,(a3) * Flag ändern
bra parameters
op_side: * Seiten ändern
lea s_sides(pc),a2 * Stringadresse
lea side(pc),a3 * Adresse im Bootsektor
move.b (a3),d0 * Seitenzahl nach d0 holen
move.b $1(a2),d1
eor.b #3,d0 * Seitenzahl ändern
eor.b #3,d1
move.b d0,(a3) * in Bootsektor schreiben
move.b d1,$1(a2) * für String aufbereiten
bra parameters
op_dir:
lea s_dir(pc),a2 * Stringadresse
lea entries(pc),a3 * Adresse der Einträge
move.b (a3),d0
move.b (a2),d1
addq.b #1,d1
add.b #16,d0 * 16 aufaddieren
cmpi.b #143,d0 * schon mehr als erlaubt?
bne wr_dir * nein, fertig
move.b #15,d0 * wieder von vorne
move.b #'1',d1
wr_dir:
move.b d0,(a3) * Bootsektor aktualisieren
move.b d1,(a2) * String aktualisieren
bra parameters
op_inter:
lea s_inter(pc),a2 * Stringadresse
lea ileave(pc),a3 * Inter1eave-Adresse
move.w (a3),d0 * Wert holen
move.b 1(a2),d1 * String holen
addq.b #1,d1
addq.b #1,d0
cmpi.b #10,d0 * schon 10?
bne wr_inter
move.w #1,d0
move.b #'1',d1
wr_inter:
move.b d1,1(a2)
move.w d0,(a3)
bra parameters
***************************
* calc_secs: Anzahl der Sektoren ausrechnen
* Formel: (endtrack+1)*11*side
****************************
calc_secs:
clr.l d1
clr.l d0
lea sectors(pc),a3
move.b endtrack(pc),d0 * Letzter Track
addq.b #1,d0 * plus eins
mulu #11,d0 * mal 11
move.b side(pc),d1
mulu d1,d0 * mal side
move.b d0,(a3) * Lowbyte schreiben
asr.l #8,d0 * Highbyte holen
move.b d0,$1(a3) * und schreiben
rts
************************
* Der Text
************************
.even
msg1:
.dc.b 27,'E',27,'P ',13,10
.dc.b 'THE HYPER FORMATTER V2.0',13,10
.dc.b '========================',13,10
.dc.b ' Written 1987 by Claus Brod ',13,10
.dc.b ' (Thanks to CD and Anton) ',27,'q',13,
.dc.b ' 927000 Bytes free & 30% faster',0
msg_parms:
.dc.b 27,'Y',32+7,32+0
.dc.b 27,'pT’,27,'q Tracks '
s_tracks:
.dc.b '83',13,10
.dc.b 27,'pE',27,'q Ausführbar (executable):'
s_exe:
.dc.b 'n',13,10
.dc.b 27,'pD',27,'q Directoryeinträge :$'
s_dir:
.dc.b '40',13,10
.dc.b 27,'pS',27,'q Seiten (sides) :'
s_sides:
.dc.b '02',13,10
.dc.b 27,'pl',27,'q interleave :'
s_inter:
.dc.b '06',13,10
.dc.b 13,10,27,'pCR',27,'q HYPERFORMAT ',13,10
.dc.b 27,'p^C',27,'q Quit',13,10
.dc.b 27,'pB ',27,'q Bootsektor etc. schreiben',13,10,0
.even
againmsg:
.dc.b 13,10,13,10,'Again (Y/N)? ',0
diskmsg:
.dc.b 13,10,'Bitte Disk in Laufwerk ',65+laufwerk,' einlegen.',13,10,0
keymsg:
.dc.b 'Taste drücken.',13,10,0
errormsg:
.dc.b 13,10,'Fehler beim Formatieren!',13,10,0
mallocmsg:
.dc.b 13,10,'MALLOC Error!',13,10,0
freemsg:
.dc.b 13,10,'MFREE Error!',13,10,0
.even
bootsector:
.dc.b 96,56,76,111,97,100,101,114
.dc.b 203,31,238,0,2,spc,res,0,fat
entries:
.dc.b 63,0
sectors:
.dc.b 34,7,249,secsperfat,0,spt,0
side:
.dc.b 2,0,0,0,0,0,0,0,0,0,0,0,0,4
.dc.b 0,0,0,0,128,0,84,79
.dc.b 83,32,32,32,32,32,73,77
.dc.b 71,0,51,250,255,226,0,0
.dc.b 4,130,63,57,0,0,4,70
.dc.b 63,60,0,7,78,77,88,79
.dc.b 74,128,103,0,0,246,42,64
.dc.b 65,250,255,208,74,144,102,6
.dc.b 32,185,0,0,4,50,48,45
.dc.b 0,8,225,72,208,128,56,64
.dc.b 217,250,255,184,48,58,255,170
.dc.b 103,16,60,58,255,166,56,58
.dc.b 255,164,38,122,255,162,96,0
.dc.b 0,180,60,45,0,10,56,45
.dc.b 0,8,216,109,0,6,38,122
.dc.b 255,146,97,0,0,178,102,0
.dc.b 0,170,32,76,48,45,0,6
.dc.b 225,72,227,72,65,240,0,0
.dc.b 67,250,255,124,144,252,0,32
.dc.b 177,204,109,0,0,142,112,10
.dc.b 18,48,0,0,178,49,0,0
.dc.b 102,234,81,200,255,244,126,0
.dc.b 30,40,0,27,225,79,30,40
.dc.b 0,26,44,122,255,78,38,122
.dc.b 255,70,66,132,190,124,15,240
.dc.b 108,82,54,7,85,67,198,237
.dc.b 0,2,214,109,0,12,184,124
.dc.b 0,64,108,8,74,68,103,14
.dc.b 182,69,103,16,97,72,102,66
.dc.b 225,140,227,140,215,196,60,3
.dc.b 58,3,66,132,216,109,0,2
.dc.b 218,109,0,2,52,7,226,74
.dc.b 212,71,18,54,32,1,225,73
.dc.b 18,54,32,0,8,7,0,0
.dc.b 103,2,232,73,194,124,15,255
.dc.b 62,1,96,368,74,68,103,4
.dc.b 97,12,102,6,47,58,254,224
.dc.b 78,117,66,128,78,117,63,57
.dc.b 0,0,4,70,63,6,63,4
.dc.b 47,11,66,103,63,60,0,4
.dc.b 78,77,222,252,0,14,74,64
.dc.b 78,117,78,101,117,116,101,114
.dc.b 32,66,111,111,116,101,114,13
.dc.b 10,40,67,41,49,57,56,53
.dc.b 32,65,116,97,114,105,32,67
.dc.b 111,114,112,46,13,10,0,0
.dc.l 0,0,0,0,0,0,0,0
.dc.l 0,0,0,0,0,0,0,0
.dc.l 0,0,0,0,0,0,0,0,0,0,0,0
cleansector:
.dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 * Je 16 Nuller
.dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
ileave:
.dc.w 6
endtrack:
.dc.b 82
executable:
.dc.w 0
fmtflag:
.dc.b 0
romflag:
.dc.b 0
.even
save_ssp:
.dc.l 0
.end