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.


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
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
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