C 64/VC 20
Floppy-Kurs

In die Geheimnisse der Floppy eingetaucht — Teil 6

Formatieren einer Diskette ist für jeden Floppy-Besitzer das erste, was er mit ihr macht. Was beim Formatieren passiert und weshalb die Floppy so nervig rattert, warum es so lange dauert und wie es schneller geht, erfahren Sie in folgendem Artikel.

Wie jedem Floppy-Besitzer bekannt ist, muß eine Diskette vor dem ersten Speichern von Daten formatiert werden. Wie eine Diskette nach einem solchen Formatiervorgang aussieht, wurde schon besprochen.

Uns soll nun interessieren, was während des Formatierens so alles in der Floppy passiert und warum die 1541 so lange für einen eigentlich sehr einfachen Vorgang benötigt.

Zur Wiederholung: Beim Formatieren werden vom DOS alle wichtigen Markierungen auf die Diskette gebracht und außerdem sämtliche Sektoren in ihrer späteren Form angelegt.

Der Vorgang des Formatierens verwendet zu seiner Ausführung einen uns schon bekannten Jobcode, nämlich $E0.

Bevor das DOS den eigentlichen Formatiervorgang startet, wird ab $0600 (also im Puffer 3) ein Sprungbefehl abgelegt: JMP $FAC7.

Dieser Sprungbefehl ist eine Art Vektor, der im RAM liegt und somit verändert werden kann. Er bietet dem Benutzer die Möglichkeit, eine eigene Routine einzubauen, die dann bei jedem Trackwechsel angesprungen wird, um so einige wirksame Manipulationen an der Formatierung vorzunehmen, indem zum Beispiel Werte in der Zeropage verändert werden, doch dazu später. Üblicherweise zeigt dieser Vektor direkt auf eine Jobroutine, die für das Formatieren zuständig ist. Diese Routine wird nun vom Hauptprogramm mit dem Jobcode $E0, der in Speicherstelle $03 geschrieben wird, aufgerufen.

Formatieren in der Jobschleife

Am Anfang der Jobroutine steht nun die Abfrage, ob schon mindestens ein Track formatiert wurde oder ob dieser Einsprung der allererste ist. Ist dieser Einsprung der erste, so werden alle Parameter für den Steppermotor gesetzt; danach erfolgt ein Rücksprung in die Jobschleife. Hier wird der Tonkopf nun 45 (!) Tracks zurückgefahren, was sich in jenem charakteristischen Rattern der Floppystation äußert.

Nun, können Sie sagen, es würde auch reichen, wenn der Kopf nur 35 oder 40 Spuren zurücktransportiert würde. In der Tat ist der Wert 45 sehr hoch. Man muß aber bedenken, daß es passieren kann, daß der Schreib-/Lesekopf der Floppy durch eine defekte Diskette oder einen Programmierfehler zu weit nach innen gefahren und beispielsweise auf Track 42 am Anschlag gelandet ist, daß ein Zurückfahren um 40 Tracks einfach nicht ausreicht, um den Tonkopf richtig zu positionieren.

Der Wert von 45 Tracks enthält also eine Sicherheitsreserve, die ein Positionieren auf Spur 1 mit Sicherheit ermöglicht.

Wurde der Kopf also auf Track 1 positioniert, so erfolgt erneut ein Einsprung in die Formatierungsroutine; eine Speicherstelle zeigt jetzt an, daß der Kopf auf Track 1 positioniert wurde und das Formatieren starten kann.

Jetzt wird noch geprüft, ob auf die nächste Spur umgeschaltet werden soll, da die aktuelle bereits formatiert wurde (wenn ja, erfolgt wieder ein Einsprung in die Jobschleife, um das Nötige zu tun).

Diese Abfragen am Anfang der Formatierungsroutine scheinen umständlich und überflüssig zu sein; das Gefühl täuscht jedoch. Wir dürfen ja nicht vergessen, daß die Routine immer nur jeweils einen Track formatiert und danach zur Jobschleife zurückkehrt, damit der Tonkopf weitergeführt werden kann. Wir haben also gewissermaßen eine Endlosschleife, die nur durch die Feststellung, daß Spur 35 fertig formatiert wurde, beendet wird.

Ausmessen einer Spur

Jetzt haben wir aber endlich alle Voraussetzungen zum Formatieren eines Tracks erfüllt und wollen an die Arbeit gehen. Der Abschnitt, der jetzt besprochen wird, ist übrigens für die langwierige Formatierung verantwortlich und sorgt für die ausgedehnten Wartezeiten.

Bevor die SYNC-Markierungen und Sektoren auf eine Spur geschrieben werden, wird diese Spur vom DOS »ausgemessen«.

Das Betriebssystem der 1541 »weiß« im Normalfall genau, wieviele Bytes für die SYNC-Markierungen und Sektoren einer Spur benötigt, beziehungsweise verbraucht werden.

Jetzt ist es aber so, daß die Sektoren nicht genau auf jede Spur abgemessen sind; vielmehr hat die Diskette pro Spur eine etwas höhere Kapazität, als eigentlich benötigt wird. Aus dieser Tatsache folgt natürlich, daß zwischen den einzelnen Sektoren »Leerstellen« entstehen, die keine Daten enthalten.

Da jetzt aber die Länge der Tracks von außen (Track 1) nach innen (Track 35) kontinuierlich abnimmt, werden diese Leerstellen immer kleiner; wir haben also unterschiedliche Anzahlen von »Leerbytes« zwischen den Sektoren.

Das DOS ist nun bestrebt, die Sektoren jeder Spur möglichst symmetrisch anzuordnen, also immer den gleichen Abstand zwischen zwei Sektoren eines Tracks zu haben. Bild 1 zeigt, was passiert, wenn keine vorherige Ausmessung stattfindet.

Bild 1. Verteilung ohne Abmessung der Abstände (schematisch).
Bild 2. Symmetrische Verteilung der Sektoren

Um das Ziel einer »symmetrisch« formatierten Diskette zu erreichen, stellt das DOS durch einige komplizierte Schreib- und Lesevorgänge das Verhältnis zwischen benötigtem und vorhandenem Platz einer Spur fest. Aus diesem Verhältnis kann nun anhand einer einfachen Rechnung festgestellt werden, wieviel Platz zwischen den einzelnen Sektoren freigelassen werden muß.

Nachdem diese komplizierte Vermessung stattgefunden hat, die mehrere Diskettenumdrehungen und damit Zeit erfordert, beginnt nun das eigentliche Formatieren der Diskette, das mit allem Drum und Dran normalerweise nicht mehr als eine ⅓ Sekunde für eine Track benötigt.

Das Anlegen der Sektoren im Puffer

Bevor geschrieben werden kann, müssen die Sektoren erst einmal im Pufferspeicher der 1541 hergestellt werden. Da sich die einzelnen Sektoren nur durch deren Header unterscheiden, reicht das Anlegen der Blockheader; die Inhalte der Datenblöcke sind bei jedem Sektor gleich und bestehen aus dem schon bekannten Muster $4B gefolgt von 255 $01-Bytes.

Die Blockheader werden alle in einem Pufferspeicher ($0300-$03FF) abgelegt; der Inhalt der Datenblöcke steht ab $0500 bis $05FF.

Schreiben eines Tracks auf Diskette

So, alle Vorarbeiten wären jetzt abgeschlossen. Wir können mit dem Schreiben auf Diskette beginnen. Zuerst wird der Disk-Controller auf Schreibmodus gestellt und die Spur der Diskette gelöscht.

Der gesamte Spurinhalt wird nun während einer einzigen Diskettenumdrehung (⅕ Sekunde) auf die Diskette gebracht, wobei zuerst die SYNC-Markierung für den Blockheader, danach der Blockheader selbst geschrieben werden. Nach einer Lücke von 9 Byte folgt die SYNC-Markierung des Datenblocks mit den zugehörigen Datenbyte. Den Abschluß eines Sektors bildet der schon erwähnte »Leerraum«, der aus der vorher errechneten Anzahl von Byte besteht.

Zur Sicherheit erfolgt nach dem Schreiben eine Verify-Routine, die auf eventuelle Disketten- oder Schreibfehler kontrolliert und bei deren Auftreten einen »24, READ ERROR« ausgibt.

Mit dieser letzten Maßnahme ist eine Spur einer Diskette fertig formatiert worden, und es wird auf Erreichen der Spur 35 abgefragt. Wurde Spur 35 formatiert, so werden alle Flags für das Formatieren zurückgesetzt, die Jobschleife verlassen und ins Hauptprogramm zurückgekehrt.

Formatieren ohne ID

Im Hauptprogramm wird nun auf Track 18 positioniert. Die BAM der Diskette wird hergestellt und in Block 18,0 abgelegt. Anschließend wird noch der erste Directory-Block (18,1) mit Nullen vollgefüllt und ebenfalls abgespeichert, womit das Formatieren abgeschlossen wäre.

Formatiert man eine Diskette nur kurz, das heißt ohne Angabe einer ID beim N-Befehl, so werden alle anfänglichen Schritte weggelassen. Es wird in diesem Fall nur auf das richtige Formatkennzeichen in der BAM ($41/65/A) kontrolliert und danach der eben beschriebene Vorgang auf Track 18 durchgeführt.

Formatieren mit »Variationen«

Nun wäre unser Floppykurs natürlich kein Floppykurs, wenn wir unsere neu gewonnenen theoretischen Kenntnisse nicht sofort in die Praxis umsetzen wollten.

In der Tat kann man mit Hilfe der Formatierroutine im DOS einige nette »Scherze« auf eine Diskette bringen, die entweder dem Spieltrieb oder dem Softwareschutz dienen können.

Ich habe vorhin schon erwähnt, daß die Formatierroutine jeweils über einen Sprungbefehl bei $0600 im RAM der Floppy aufgerufen wird.

Diese Adresse wird bei jedem neuen Track angesprungen und bietet so die Möglichkeit, Tracks zu erzeugen, die in ihrem Aufbau voneinander abweichen, wenn entsprechende Eingriffe vorgenommen werden.

Diese Möglichkeit eines Eingriffes wollen wir an dieser Stelle aber gar nicht erst weiter diskutieren, da es ziemlich aussichtslos ist, hier ohne dokumentiertes DOS-Listing an die Arbeit zu gehen.

Daß wir kein DOS Listing besitzen, soll aber noch lange nicht heißen, daß wir nicht in der Lage sind, auf anderem Weg, Eingriffe in die Formatierung vorzunehmen. Wenn wir nicht effektiv mit der fest eingebauten Routine zusammenarbeiten können, dann schreiben wir uns eben ein vollständig eigenes Programm, das im RAM der Floppy abgelegt wird und uns für Abänderungen unendlich viele Möglichkeiten bietet.

Formatierung »selbst gebaut«

Sehen Sie sich einmal Listing 1 an. Ich habe hier ein Formatiersystem entwickelt, das einfacher und schneller arbeitet als die DOS-Routine und trotzdem ein paar zusätzliche Möglichkeiten bietet.

Da das Gesamtprinzip aber fast 100prozentig mit der im DOS eingebauten Routine übereinstimmt, können Sie sich anhand des Source-Code-Listings einmal die »praktische Ausführung« einer Formatierroutine ansehen.

Um Ihnen die Eingabe des Programms zu erleichtern, habe ich einen DATA-Lader als Listing 2 beigefügt, wobei ich Ihnen empfehlen möchte, diesen gleich einmal einzutippen.

Das Programm wird nur aktiviert, wenn alle DATAs richtig eingetippt wurden. Haben Sie alles richtig gemacht, so steht nach der Ausführung des Laders ein Maschinenprogramm am Basic-Anfang, dem eine Basic-Zeile beigefügt ist. Das Programm sollten Sie sich jetzt mit SAVE auf eine Diskette speichern und danach mit RUN starten.

Nach einer winzigen Verzögerung erscheint die READY-Meldung und der Cursor wieder. Das Formatierungsprogramm wurde jetzt in den Bereich ab $C000 (49152) geschoben und der SAVE-Vektor abgeändert.

Tippen Sie jetzt einfach den Befehl SAVE — ohne Anführungszeichen und Filenamen — ein und drücken Sie RETURN. Es erscheint nun die Startmeldung des Formatprogrammes. Sie können jetzt einen Namen für eine Diskette eingeben (maximal 16 Zeichen werden angenommen). Danach erwartet der Computer eine zweistellige ID. Schließlich, und das ist das besondere an diesem Programm, können Sie noch den ersten und letzten zu formatierenden Track eingeben. Diese Eingabe muß hexadezimal erfolgen und erlaubt einen Bereich von $01 bis $FF.

Achtung! Wird eine Zahl größer als $29 (41) eingegeben, wird es in der Regel kritisch. Der Kopf ist dann nämlich am oberen Anschlagpunkt angelangt.

Etwas ist noch zu beachten: Ein Nachformatieren einer Spur auf einer gefüllten Diskette ist mit dem Programm ohne Änderung nicht möglich, da das Directory auf jeden Fall neu geschrieben wird. Wird die Diskette nicht vollständig formatiert, so ist darauf zu achten, daß die gleiche ID eingegeben wird, wie sie schon für die übrige Diskette Gültigkeit hat, da es sonst einen »29, DISK ID MISMATCH ERROR« gibt.

Wollen Sie dennoch einen Einzeltrack neu formatieren, ohne das Directory zu zerstören, so können Sie das durch eine einfache Änderung im Floppy-Programm erreichen. Sie gehen in Listing la an die Adresse $06B5. Den Befehl JSR $EE40 und das nachfolgende RTS ersetzen Sie durch lauter NOPs.

Eine Änderung des Directory-Track unterbleibt jetzt, sofern Sie die Tracknummern zur Formatierung entsprechend wählen, da dieser Befehl die Routine zum kurzen Formatieren im DOS aufgerufen hätte.

In jedem Fall gilt aber: Bei Formatieren von Einzeltracks müssen diese die gleiche ID wie die übrige Diskette erhalten.

Eine weitere Möglichkeit dient der Schonung des Laufwerks. Wenn Sie sich das Floppy-Programm noch einmal betrachten, dann finden Sie bei Adresse $0696 den Befehl an den Disk-Controller, einen BUMP auszuführen. Wenn Sie hier das $C0 durch ein $00 ersetzen, dann unterbleibt dieses Anschlagen des Tonkopfes am Anfang des Formatierens. Diese Maßnahme ist immer dann nützlich, wenn mehrere Disketten hintereinander formatiert werden sollen.

Zur Zeitdauer ist noch zu sagen, daß das Programm für eine Diskette zirka 30 Sekunden benötigt und damit um einiges schneller ist als das Programm im DOS der 1541. Warum das so ist, wollen wir gleich erfahren.

Geschwindigkeit; aber wie?

In meinem Formatierprogramm wurde die Berechnung der Lücke zwischen zwei Sektoren weggelassen. Wir können nämlich davon ausgehen, daß diese Lücken auf jeder Diskette in etwa gleich sind. Aus diesem Grund verwende ich einfach einen Erfahrungswert für die Länge der Lücke, der zusätzlich noch einen Sicherheitsbereich enthält. Diesen Wert sehen Sie in Listing la an der Adresse $05DF.

Wenn Sie mit dem Programm Disketten formatieren, werden Sie feststellen, daß die Datensicherheit auch weiterhin voll gewährleistet ist.

Im Gegensatz zu anderen schnellen Formatierprogrammen habe ich aber nicht auf ein Verify verzichtet, da das Formatieren die einzige Möglichkeit bietet, defekte Disketten rechtzeitig zu erkennen, ohne daß dabei wichtige Daten verlorengehen. Einmal ganz davon abgesehen, macht das Verifizieren außerdem nur einen sehr kleinen Teil am Geschwindigkeitsverlust aus, so daß die Sicherheit vor einigen Sekunden Zeitgewinn Vorrang haben sollte.

Wollen Sie die Zeit dennoch einmal ohne Verify messen, so »klemmen« sie den Rest der Formatierungsroutine ab $05FD ganz einfach ab, indem Sie an dieser Stelle nach JMP $FE00 ein JMP $FD9E einfügen. Eine weitere Verbesserung gegenüber dem DOS 2.6 der 1541 hat eigentlich mehr kosmetischen Charakter.

Es geht hier um den Leerinhalt von Datenblöcken, nachdem eine Diskette neu formatiert wurde. Den Inhalt werden Sie höchstwahrscheinlich schon kennen: Es steht am Anfang des Datenblocks ein $4B gefolgt von 255 $01-Bytes.

Dieser Inhalt ist eigentlich auf einen Fehler im DOS zurückzuführen; er müßte, wie auch bei den großen Commodore-Floppies aus 256 $00-Bytes bestehen.

In meinem Programm fülle ich alle Sektoren mit dem üblichen Wert $00.

Noch ein paar Hinweise zur Benutzung des Formatierprogramms.

Nach RUN wird automatisch der SAVE-Vektor auf den Programmstart der Formatierroutine gestellt. Wird kein Filename angegeben, so erfolgt ein Sprung in das Formatierprogramm. Durch Drücken von RUN STOP/RESTORE läßt sich der SAVE-Vektor wieder richtig »hinbiegen«. Hierzu dürfte jedoch kein Anlaß bestehen, da bei fehlendem Filenamen kein Programm gestartet wird.

Mußten Sie dennoch einmal RESTORE drücken, so läßt sich das Formatier-System mit SYS 49664 ($C200) erneut starten; nach Beendigung wird unter anderem auch der SAVE-Vektor wieder auf das Programm zurückgestellt.

Wollen Sie sich den Disk-Status anzeigen lassen, so tippen Sie SYS49962. Es erscheint danach auch die Frage nach einem weiteren Formatiervorgang, die Sie entsprechend beantworten. Nach dieser Anzeige wird der SAVE-Vektor ebenfalls wieder hergestellt.

Ich möchte Sie an dieser Stelle auf ein paar Speicherstellen in der Zeropage der 1541 aufmerksam machen. Wie Sie wissen, werden dort nach einem RESET ein paar Konstanten abgelegt, die vom Benutzer (beliebig) verändert werden können. Mit den Konstanten meine ich zum Beispiel $08 als Kennzeichen eines Blockheaders oder $07 als Kennzeichen eines Datenblocks.

Wie Sie aus der Zeropage-Belegung in der 64’er-Ausgabe 1/1985, Seite 151 entnehmen können, werden diese beiden Werte in den Speicherstellen $38 (Wert 07) und $39 (Wert 08) abgelegt und können nun abgeändert werden. Der neue Wert, den Sie vielleicht in diese Speicherstellen eintragen, sollte sich jedoch im Bereich von $00 bis $0F bewegen, da es sonst Schwierigkeiten beim Lesen geben kann. Die Folge eines Leseversuchs mit normalen Werten, wenn eine Diskette anders formatiert wurde, sind entweder ein »20, READ ERROR« oder ein »22, READ ERROR«.

Der Vorteil dieser Errors ist jedoch die Möglichkeit, den Blöcken auch Inhalte mitzugeben, womit ein sehr wirkungsvoller Kopierschutz konstruiert werden kann.

Zum Lesen oder Beschreiben der Diskette müssen die Werte in den beiden Speicherstellen nur jeweils richtig gestellt werden; dann kann ein ganz normaler Zugriff stattfinden.

Mit Hilfe des Formatierprogramms können Sie jetzt auch noch zusätzlich illegale Spuren beschreiben. Hierbei müssen Sie allerdings, wie in der letzten Folge besprochen, auf Jobschleifenebene arbeiten, um die Begrenzung auf die Spuren 1 bis 35 zu umgehen.

In der nächsten Folge möchte ich Ihnen etwas vorstellen, das sich GCR-Codierung nennt. Wir werden dann erfahren, daß Daten keineswegs so auf Diskette geschrieben werden, wie sie im Puffer vorliegen, sondern, daß vorher eine Codierung erfolgt.

(Karsten Schramm/gk)
Floppyprogramm zum Disk-Format-System
    1985 by KOSS
0500  ea        nop
0501  a5 0a     lda $0a      Tracknummer aus Jobspeicher
0503  c9 24     cmp #$24     größer als 35?
0505  90 07     bcc $050e    nein
0507  a9 12     lda #$12     ja: 18 als Anzahl der Sektoren
0509  85 43     sta $43      festlegen
050b  4c 13 05  jmp $0513
050e  20 4b f2  jsr $f24b    Anzahl der Sektoren holen
0511  85 43     sta $43      und merken
0513  a9 00     lda #$00
0515  85 1b     sta $1b      Sektorzähler setzen
0517  a0 00     ldy #$00
0519  a2 00     ldx #$00
051b  a5 39     lda $39      Kennzeichen $08 für Blockheader
051d  99 00 03  sta $0300,y
0520  c8        iny
0521  c8        iny
0522  a5 1b     lda $1b      Sektornummer
0524  99 00 03  sta $0300,y
0527  c8        iny
0528  a5 0a     lda $0a      Tracknummer
052a  99 00 03  sta $0300,y
052d  c8        iny
052e  a5 13     lda $13      ID 2
0530  99 00 03  sta $0300,y
0533  c8        iny
0534  a5 12     lda $12      ID 1
0536  99 00 03  sta $0300,y
0539  c8        iny
053a  a9 0f     lda #$0f
053c  99 00 03  sta $0300,y  Lücke lassen
053f  c8        iny
0540  99 00 03  sta $0300,y
0543  c8        iny
0544  a9 00     lda #$00
0546  59 fa 02  eor $02fa,y  Prüfsumme bilden
0549  59 fb 02  eor $02fb,y
054c  59 fc 02  eor $02fc,y
054f  59 fd 02  eor $02fd,y
0552  99 f9 02  sta $02f9,y  und abspeichern
0555  e6 1b     inc $1b
0557  a5 1b     lda $1b      Sektorzähler erhöhen
0559  c5 43     cmp $43      schon Maximalzahl?
055b  90 be     bcc $051b    nein, weitermachen
055d  a9 03     lda #$03
055f  85 31     sta $31
0561  98        tya
0562  48        pha
0563  8a        txa
0564  9d 00 07  sta $0700,x  Datenblock mit $00 füllen
0567  e8        inx
0568  d0 fa     bne $0564
056a  20 30 fe  jsr $fe30
056d  68        pla
056e  a8        tay
056f  88        dey
0570  20 e5 fd  jsr $fde5
0573  20 f5 fd  jsr $fdf5
0576  a9 07     lda #$07
0578  85 31     sta $31
057a  20 e9 f5  jsr $f5e9    Prüfsumme für Datenblock
057d  85 3a     sta $3a      abspeichern
057f  20 8f f7  jsr $f78f
0582  a9 00     lda #$00     Sektorzähler setzen
0584  85 32     sta $32
0586  20 0e fe  jsr $fe0e    Track löschen
0589  a9 ff     lda #$ff
058b  8d 01 1c  sta $1c01    SYNC schreiben
058e  a2 05     ldx #$05
0590  50 fe     bvc $0590
0592  b8        clv
0593  ca        dex
0594  d0 fa     bne $0590
0596  a2 0a     ldx #$0a
0598  a4 32     ldy $32
059a  50 fe     bvc $059a    Blockheader schreiben
059c  b8        clv
059d  b9 00 03  lda $0300,y
05a0  8d 01 1c  sta $1c01
05a3  c8        iny
05a4  ca        dex
05a5  d0 f3     bne $059a
05a7  a2 09     ldx #$09
05a9  50 fe     bvc $05a9    Lücke von 9 Bytes lassen
05ab  b8        clv
05ac  a9 55     lda #$55
05ae  8d 01 1c  sta $1c01
05b1  ca        dex
05b2  d0 f5     bne $05a9
05b4  a9 ff     lda #$ff
05b6  a2 05     ldx #$05
05b8  50 fe     bvc $05b8    SYNC-Markierung für Datenblock
05ba  b8        clv
05bb  8d 01 1c  sta $1c01
05be  ca        dex
05bf  d0 f7     bne $05b8
05c1  a2 bb     ldx #$bb
05c3  50 fe     bvc $05c3
05c5  b8        clv
05c6  bd 00 01  lda $0100,x
05c9  8d 01 1c  sta $1c01
05cc  e8        inx
05cd  d0 f4     bne $05c3
05cf  a0 00     ldy #$00
05d1  50 fe     bvc $05d1    Datenblock schreiben
05d3  b8        clv
05d4  b1 30     lda ($30),y
05d6  8d 01 1c  sta $1c01
05d9  c8        iny
05da  d0 f5     bne $05d1
05dc  a9 55     lda #$55
05de  a2 08     ldx #$08     Lücke nach Sektor mit fester
05e0  50 fe     bvc $05e0    Länge von 8 Bytes schreiben
05e2  b8        clv
05e3  8d 01 1c  sta $1c01
05e6  ca        dex
05e7  d0 f7     bne $05e0
05e9  a5 32     lda $32
05eb  18        clc
05ec  69 0a     adc #$0a
05ee  85 32     sta $32
05f0  c6 1b     dec $1b      schon alle Sektoren?
05f2  d0 95     bne $0589    nein, weitermachen
05f4  50 fe     bvc $05f4
05f6  b8        clv
05f7  50 fe     bvc $05f7
05f9  b8        clv
05fa  20 00 fe  jsr $fe00    auf Lesen umschalten
05fd  a9 c8     lda #$c8     200 Leseversuche
05ff  85 1f     sta $1f
0601  a9 00     lda #$00
0603  85 30     sta $30
0605  a9 03     lda #$03
0607  85 31     sta $31
0609  a5 43     lda $43
060b  85 1b     sta $1b      Sektorzähler
060d  20 56 f5  jsr $f556    auf SYNC-Signal warten
0610  a2 0a     ldx #$0a
0612  a0 00     ldy #$00
0614  50 fe     bvc $0614
0616  b8        clv
0617  ad 01 1c  lda $1c01
061a  d1 30     cmp ($30),y  Daten vergleichen
061c  d0 0e     bne $062c
061e  c8        iny
061f  ca        dex
0620  d0 f2     bne $0614
0622  18        clc
0623  a5 30     lda $30
0625  69 0a     adc #$0a
0627  85 30     sta $30
0629  4c 35 06  jmp $0635
062c  c6 1f     dec $1f      Zähler vermindern
062e  d0 d1     bne $0601
0630  a9 06     lda #$06
0632  4c d3 fd  jmp $fdd3    24, READ ERROR
0635  20 56 f5  jsr $f556    SYNC-Signal abwarten
0638  a0 bb     ldy #$bb
063a  50 fe     bvc $063a
063c  b8        clv
063d  ad 01 1c  lda $1c01
0640  d9 00 01  cmp $0100,y
0643  d0 e7     bne $062c
0645  c8        iny
0646  d0 f2     bne $063a
0648  a2 fc     ldx #$fc
064a  50 fe     bvc $064a
064c  b8        clv
064d  ad 01 1c  lda $1c01
0650  d9 00 07  cmp $0700,y  Datenblock testen
0653  d0 d7     bne $062c
0655  c8        iny
0656  ca        dex
0657  d0 f1     bne $064a
0659  c6 1b     dec $1b
065b  d0 b0     bne $060d
065d  4c 9e fd  jmp $fd9e    Ende; zur Jobschleife
0660  a0 00     ldy #$00     Start des Floppyprogramms
0662  b9 e0 06  lda $06e0,y
0665  99 00 02  sta $0200,y  Disknamen übernehmen
0668  c8        iny
0669  cc df 06  cpy $06df
066c  90 f4     bcc $0662
066e  ad df 06  lda $06df
0671  8d 74 02  sta $0274    Länge der Zeile setzen
0674  ad de 06  lda $06de
0677  8d 7b 02  sta $027b    Kommaposition setzen
067a  a9 00     lda #$00
067c  85 7f     sta $7f      Drive 0 setzen
067e  20 00 c1  jsr $c100    LED am Laufwerk an
0681  ac 7b 02  ldy $027b
0684  b9 00 02  lda $0200,y  ID 1 holen
0687  85 12     sta $12
0689  b9 01 02  lda $0201,y  id 2 holen
068c  85 13     sta $13
068e  20 07 d3  jsr $d307    alle Kanäle schließen
0691  a9 1a     lda #$1a
0693  8d 05 1c  sta $1c05    Timer setzen
0696  a9 c0     lda #$c0     BUMP anfordern
0698  85 00     sta $00
069a  a5 00     lda $00
069c  30 fc     bmi $069a    auf Ausführung warten
069e  ae dc 06  ldx $06dc    erste Tracknummer
06a1  86 0a     stx $0a
06a3  a9 e0     lda #$e0     Track formatieren
06a5  85 02     sta $02
06a7  a5 02     lda $02
06a9  30 fc     bmi $06a7    auf Ende warten
06ab  c9 02     cmp #$02     Fehler aufgetreten?
06ad  b0 0c     bcs $06bb    verzweige, wenn ja
06af  e8        inx
06b0  ec dd 06  cpx $06dd    schon Zieltrack formatiert?
06b3  90 ec     bcc $06a1    weiter, wenn nein
06b5  20 40 ee  jsr $ee40    Directory herstellen
06b8  60        rts          Ende
06b9  ea        nop
06ba  ea        nop
06bb  a2 02     ldx #$02
06bd  4c 0a e6  jmp $e60a    Diskstatus ausgeben; Ende
Listing 1a. Das Floppy-Programm zum Format-System
   Computerprogramm zum Disk-Format-System
   (c) 1985 by KOSS
., c200 a2 00      ldx #$00
., c202 20 87 c2   jsr $c287         Titel und erste Frage ausgeben
., c205 a0 00      ldy #$00
., c207 20 cf ff   jsr $ffcf         Eingabe holen
., c20a c9 0d      cmp #$0d
., c20c f0 08      beq $c216
., c20e 99 e0 c1   sta $c1e0,y       Namen abspeichern
., c211 c8         iny
., c212 c0 10      cpy #$10          schon 16 Zeichen?
., c214 90 f1      bcc $c207         weiter, wenn nein
., c216 a9 2c      lda #$2c          Komma hinter den Namen setzen
., c218 99 e0 c1   sta $c1e0,y
., c21b c8         iny
., c21c 8c de c1   sty $c1de
., c21f a2 47      ldx #$47
., c221 20 87 c2   jsr $c287         Frage nach Disk-ID
., c224 a2 00      ldx #$00
., c226 20 cf ff   jsr $ffcf         Eingabe abwarten
., c229 c9 0d      cmp #$0d
., c22b f0 09      beq $c236
., c22d 99 e0 c1   sta $c1e0,y       ID ebenfalls abspeichern
., c230 c8         iny
., c231 e8         inx
., c232 e0 02      cpx #$02
., c234 90 f0      bcc $c226
., c236 8c df c1   sty $c1df
., c239 a2 53      ldx #$53
., c23b 20 87 c2   jsr $c287         'FROM TRACK:$' ausgeben
., c23e 20 cf ff   jsr $ffcf
., c241 85 fa      sta $fa
., c243 20 cf ff   jsr $ffcf
., c246 85 fb      sta $fb
., c248 a9 00      lda #$00
., c24a 85 d0      sta $d0
., c24c a2 62      ldx #$62
., c24e 20 87 c2   jsr $c287         'TO TRACK:$' ausgeben
., c251 20 cf ff   jsr $ffcf
., c254 85 fc      sta $fc
., c256 20 cf ff   jsr $ffcf
., c259 85 fd      sta $fd
., c25b a9 00      lda #$00
., c25d 85 d0      sta $d0
., c25f a5 fa      lda $fa
., c261 a6 fb      ldx $fb
., c263 20 04 c4   jsr $c404         Umrechnung in HEX-Byte
., c266 8d dc c1   sta $c1dc         Anfangstrack setzen
., c269 a5 fc      lda $fc
., c26b a6 fd      ldx $fd
., c26d 20 04 c4   jsr $c404         Umrechnung in HEX-Byte
., c270 8d dd c1   sta $c1dd         Endetrack setzen
., c273 ee dd c1   inc $c1dd         plus 1 als Vergleichswert
., c276 ea         nop
., c277 ea         nop
., c278 ea         nop
., c279 ea         nop
., c27a ea         nop
., c27b ea         nop
., c27c ea         nop
., c27d ea         nop
., c27e ea         nop
., c27f ea         nop
., c280 ea         nop
., c281 ea         nop
., c282 ea         nop
., c283 ea         nop
., c284 4c 93 c2   jmp $c293         weiter

., c287 bd 4d c3   lda $c34d,x       Ausgabe der Texte
., c28a f0 06      beq $c292
., c28c 20 d2 ff   jsr $ffd2
., c28f e8         inx
., c290 d0 f5      bne $c287
., c292 60         rts

., c293 a9 0d      lda #$0d
., c295 20 d2 ff   jsr $ffd2
., c298 a9 0d      lda #$0d
., c29a 20 d2 ff   jsr $ffd2
., c29d a9 00      lda #$00
., c29f a2 c0      ldx #$c0
., c2a1 85 a7      sta $a7
., c2a3 86 a8      stx $a8
., c2a5 a9 00      lda #$00
., c2a7 a2 05      ldx #$05
., c2a9 85 a9      sta $a9
., c2ab 86 aa      stx $aa
., c2ad a9 08      lda #$08          LISTEN für Gerät Nummer 8
., c2af 20 b1 ff   jsr $ffb1
., c2b2 a9 6f      lda #$6f          15; Kommandokanal
., c2b4 20 93 ff   jsr $ff93
., c2b7 a9 4d      lda #$4d
., c2b9 20 a8 ff   jsr $ffa8         Programm zur Floppy senden
., c2bc a9 2d      lda #$2d
., c2be 20 a8 ff   jsr $ffa8
., c2c1 a9 57      lda #$57
., c2c3 20 a8 ff   jsr $ffa8
., c2c6 a0 00      ldy #$00
., c2c8 a5 a9      lda $a9
., c2ca 20 a8 ff   jsr $ffa8
., c2cd a5 aa      lda $aa
., c2cf 20 a8 ff   jsr $ffa8
., c2d2 a9 1e      lda #$1e
., c2d4 20 a8 ff   jsr $ffa8
., c2d7 b1 a7      lda ($a7),y
., c2d9 20 a8 ff   jsr $ffa8
., c2dc c8         iny
., c2dd c0 1e      cpy #$1e
., c2df 90 f6      bcc $c2d7
., c2e1 20 ae ff   jsr $ffae
., c2e4 18         clc
., c2e5 a5 a7      lda $a7
., c2e7 69 1e      adc #$1e
., c2e9 85 a7      sta $a7
., c2eb 90 03      bcc $c2f0
., c2ed e6 a8      inc $a8
., c2ef 18         clc
., c2f0 a5 a9      lda $a9
., c2f2 a6 aa      ldx $aa
., c2f4 69 1e      adc #$1e
., c2f6 85 a9      sta $a9
., c2f8 90 02      bcc $c2fc
., c2fa e6 aa      inc $aa
., c2fc e0 07      cpx #$07
., c2fe 90 ad      bcc $c2ad
., c300 c9 00      cmp #$00
., c302 90 a9      bcc $c2ad
., c304 a9 08      lda #$08          LISTEN für Gerät 8
., c306 20 b1 ff   jsr $ffb1
., c309 a9 6f      lda #$6f          15; Kommandokanal
., c30b 20 93 ff   jsr $ff93
., c30e a9 4d      lda #$4d
., c310 20 a8 ff   jsr $ffa8         Programm in der Floppy
., c313 a9 2d      lda #$2d          bei Adresse $0600 starten
., c315 20 a8 ff   jsr $ffa8
., c318 a9 45      lda #$45
., c31a 20 a8 ff   jsr $ffa8
., c31d a9 60      lda #$60
., c31f 20 a8 ff   jsr $ffa8
., c322 a9 06      lda #$06
., c324 20 a8 ff   jsr $ffa8
., c327 20 ae ff   jsr $ffae
., c32a a9 00      lda #$00
., c32c 85 90      sta $90
., c32e a9 08      lda #$08          Fehlermeldung holen
., c330 20 b4 ff   jsr $ffb4
., c333 a9 6f      lda #$6f
., c335 20 96 ff   jsr $ff96
., c338 20 a5 ff   jsr $ffa5
., c33b 20 d2 ff   jsr $ffd2         und anzeigen
., c33e 24 90      bit $90
., c340 50 f6      bvc $c338
., c342 20 ab ff   jsr $ffab
., c345 4c dc c3   jmp $c3dc         Endebehandlung

.: c348 00 00 00 00 00 93 20 20 ......
.: c350 20 20 20 20 20 2a 2a 2a      ***
.: c358 20 44 49 53 4b 2d 46 4f  disk-fo
.: c360 52 4d 41 54 2d 53 59 53 rmat-sys
.: c368 54 45 4d 20 2a 2a 2a 0d tem ***.
.: c370 0d 0d 20 28 43 29 20 31 .. (c) 1
.: c378 39 38 35 20 42 59 20 4b 985 by k
.: c380 4f 53 53 20 20 20 0d 0d oss   ..
.: c388 0d 44 49 53 4b 4e 41 4d .disknam
.: c390 45 3a 20 00 0d 0d 44 49 e: ...di
.: c398 53 4b 2d 49 44 3a 20 00 sk-id: .
.: c3a0 0d 0d 46 52 4f 4d 20 54 ..from t
.: c3a8 52 41 43 4b 3a 24 00 0d rack:$..
.: c3b0 0d 54 4f 20 54 52 41 43 .to trac
.: c3b8 4b 3a 24 00 0d 0d 41 4e k:$...an
.: c3c0 4f 54 48 45 52 20 46 4f other fo
.: c3c8 52 4d 41 54 20 28 59 2f rmat (y/
.: c3d0 4e 29 20 3f 20 0d 0d 00 n) ? ...
.: c3d8 00 00 00 00 20 29 c4 a2 .... )..

., c3dc 20 29 c4 jsr $c429           SAVE-Vektor stellen
., c3df a2 6f    ldx #$6f
., c3e1 20 87 c2 jsr $c287           'ANOTHER FORMAT (Y/N) ?' ausgeben
., c3e4 20 e4 ff jsr $ffe4
., c3e7 f0 fb    beq $c3e4
., c3e9 c9 59    cmp #$59            Ende ?
., c3eb d0 03    bne $c3f0           ja: RTS
., c3ed 4c 00 c2 jmp $c200           noch einmal formatieren
., c3f0 60       rts
., c3f1 00       brk
., c3f2 a5 b7    lda $b7             Länge des Filenamens =0?
., c3f4 f0 03    beq $c3f9           ja; dann formatieren
., c3f6 4c ed f5 jmp $f5ed           zur SAVE-Routine
., c3f9 20 00 c2 jsr $c200           formatieren
., c3fc a9 01    lda #$01
., c3fe a2 00    ldx #$00
., c400 a0 00    ldy #$00
., c402 18       clc
., c403 60       rts                 Ende

., c404 85 02    sta $02             Umrechnung der Eingabe in ein
., c406 86 03    stx $03             HEX-Byte
., c408 a5 02    lda $02
., c40a c9 41    cmp #$41
., c40c 90 03    bcc $c411
., c40e 18       clc
., c40f 69 09    adc #$09
., c411 29 0f    and #$0f
., c413 0a       asl
., c414 0a       asl
., c415 0a       asl
., c416 0a       asl
., c417 85 02    sta $02
., c419 a5 03    lda $03
., c41b c9 41    cmp #$41
., c41d 90 03    bcc $c422
., c41f 18       clc
., c420 69 09    adc #$09
., c422 29 0f    and #$0f
., c424 05 02    ora $02
., c426 85 02    sta $02
., c428 60       rts

., c429 a9 f2    lda #$f2            SAVE-Vektor herstellen
., c42b 8d 32 03 sta $0332
., c42e a9 c3    lda #$c3            auf Adresse $c3f2 setzen
., c430 8d 33 03 sta $0333
., c433 60       rts
Listing 1. Eine neue Formatierroutine. Eine Diskette wird nicht nur schneller sondern Sie können auch angeben, welche formatiert werden sollen. Was das für Vorteile hat, erfahren Sie im Bericht. Zwischen den Adressen C348 und C3DA liegt eine ASCII-Tabelle
10 rem ************************
20 rem *                      *
30 rem *  disk-format-system  *
40 rem *                      *
50 rem *   (c) 1985 by koss   *
60 rem *                      *
70 rem ************************
80 data 5657,5638,6947,7770,8264,7062,8578,6111,3989,3215,9192,10797
90 data 8104,8232,8308,3524,3180,5204,4577
100 data 0,14,8,10,0,158,32,50,48,54,52,32,32,0,0,0,162,64,160,8,134,2,132,3
110 data 162,0,160,192,134,4,132,5,160,0,162,5,177,2,145,4,200,208,249,230,3
120 data 230,5,202,208,242,120,169,242,141,50,3,169,195,141,51,3,88,96,234,234
130 data 165,10,201,36,144,7,169,18,133,67,76,19,5,32,75,242,133,67,169,0,133
140 data 27,160,0,162,0,165,57,153,0,3,200,200,165,27,153,0,3,200,165,10,153
150 data 0,3,200,165,19,153,0,3,200,165,18,153,0,3,200,169,15,153,0,3,200,153
160 data 0,3,200,169,0,89,250,2,89,251,2,89,252,2,89,253,2,153,249,2,230,27
170 data 165,27,197,67,144,190,169,3,133,49,152,72,138,157,0,7,232,208,250,32
180 data 48,254,104,168,136,32,229,253,32,245,253,169,7,133,49,32,233,245,133
190 data 58,32,143,247,169,0,133,50,32,14,254,169,255,141,1,28,162,5,80,254
200 data 184,202,208,250,162,10,164,50,80,254,184,185,0,3,141,1,28,200,202,208
210 data 243,162,9,80,254,184,169,85,141,1,28,202,208,245,169,255,162,5,80,254
220 data 184,141,1,28,202,208,247,162,187,80,254,184,189,0,1,141,1,28,232,208
230 data 244,160,0,80,254,184,177,48,141,1,28,200,208,245,169,85,162,8,80,254
240 data 184,141,1,28,202,208,247,165,50,24,105,10,133,50,198,27,208,149,80
250 data 254,184,80,254,184,32,0,254,169,200,133,31,169,0,133,48,169,3,133,49
260 data 165,67,133,27,32,86,245,162,10,160,0,80,254,184,173,1,28,209,48,208
270 data 14,200,202,208,242,24,165,48,105,10,133,48,76,53,6,198,31,208,209,169
280 data 6,76,211,253,32,86,245,160,187,80,254,184,173,1,28,217,0,1,208,231
290 data 200,208,242,162,252,80,254,184,173,1,28,217,0,7,208,215,200,202,208
300 data 241,198,27,208,176,76,158,253,160,0,185,224,6,153,0,2,200,204,223,6
310 data 144,244,173,223,6,141,116,2,173,222,6,141,123,2,169,0,133,127,32,0
320 data 193,172,123,2,185,0,2,133,18,185,1,2,133,19,32,7,211,169,26,141,5,28
330 data 169,192,133,0,165,0,48,252,174,220,6,134,10,169,224,133,2,165,2,48
340 data 252,201,2,176,12,232,236,221,6,144,236,32,64,238,96,234,234,162,2,76
350 data 10,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
360 data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
370 data 162,0,32,135,194,160,0,32,207,255,201,13,240,8,153,224,193,200,192
380 data 16,144,241,169,44,153,224,193,200,140,222,193,162,71,32,135,194,162
390 data 0,32,207,255,201,13,240,9,153,224,193,200,232,224,2,144,240,140,223
400 data 193,162,83,32,135,194,32,207,255,133,250,32,207,255,133,251,169,0,133
410 data 208,162,98,32,135,194,32,207,255,133,252,32,207,255,133,253,169,0,133
420 data 208,165,250,166,251,32,4,196,141,220,193,165,252,166,253,32,4,196,141
430 data 221,193,238,221,193,234,234,234,234,234,234,234,234,234,234,234,234
440 data 234,234,76,147,194,189,77,195,240,6,32,210,255,232,208,245,96,169,13
450 data 32,210,255,169,13,32,210,255,169,0,162,192,133,167,134,168,169,0,162
460 data 5,133,169,134,170,169,8,32,177,255,169,111,32,147,255,169,77,32,168
470 data 255,169,45,32,168,255,169,87,32,168,255,160,0,165,169,32,168,255,165
480 data 170,32,168,255,169,30,32,168,255,177,167,32,168,255,200,192,30,144
490 data 246,32,174,255,24,165,167,105,30,133,167,144,3,230,168,24,165,169,166
500 data 170,105,30,133,169,144,2,230,170,224,7,144,173,201,0,144,169,169,8
510 data 32,177,255,169,111,32,147,255,169,77,32,168,255,169,45,32,168,255,169
520 data 69,32,168,255,169,96,32,168,255,169,6,32,168,255,32,174,255,169,0,133
530 data 144,169,8,32,180,255,169,111,32,150,255,32,165,255,32,210,255,36,144
540 data 80,246,32,171,255,76,220,195,0,0,0,0,0,147,32,32,32,32,32,32,32,42
550 data 42,42,32,68,73,83,75,45,70,79,82,77,65,84,45,83,89,83,84,69,77,32,42
560 data 42,42,13,13,13,32,40,67,41,32,49,57,56,53,32,66,89,32,75,79,83,83,32
570 data 32,32,13,13,13,68,73,83,75,78,65,77,69,58,32,0,13,13,68,73,83,75,45
580 data 73,68,58,32,0,13,13,70,82,79,77,32,84,82,65,67,75,58,36,0,13,13,84
590 data 79,32,84,82,65,67,75,58,36,0,13,13,65,78,79,84,72,69,82,32,70,79,82
600 data 77,65,84,32,40,89,47,78,41,32,63,32,13,13,0,0,0,0,0,32,41,196,162,111
610 data 32,135,194,32,228,255,240,251,201,89,208,3,76,0,194,96,0,165,183,240
620 data 3,76,237,245,32,0,194,169,1,162,0,160,0,24,96,133,2,134,3,165,2,201
630 data 65,144,3,24,105,9,41,15,10,10,10,10,133,2,165,3,201,65,144,3,24,105
640 data 9,41,15,5,2,133,2,96,169,242,141,50,3,169,195,141,51,3,96,0
1000 rem
1010 rem **** datas initialisieren
1020 rem
1030 restore:print:print:print"datas werden ueberprueft !!!":print:print
1040 clr:dim p(19):dim w(19)
1050 for x=0 to 18:read p(x):p=p+p(x):next
1060 if p<>124349 then print"pruefsummenfehler":print:print:list 80-90
1070 for x=0 to 18:for y=0 to 59:read a:w(x)=w(x)+a:next y
1080 ifw(x)<>p(x)then 1150
1090 next x
1100 print:print"die datas sind ok und werden":print:print"abgespeichert!"
1110 restore:for x=0 to 18:read a:next
1120 for x=0 to 1139:read a:poke x+2048,a:next
1130 poke 45,119:poke 174,119:poke 46,12:poke 175,12:clr
1140 print:print"mit 'save' abspeichern!":print:end
1150 rem fehlerbehandlung
1160 print:print"fehler in den datas"x*60" bis"x*60+59" !":z=int(x*600/17.8)
1170 print:print:print"das entspricht in etwa den              {down}zeilen ab"z
1180 end
Listing 2. Der DATA-Lader der Formatierroutine
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →