readtrack:
;Diese Routine liest einen Track und entfernt die LÜcke.
;A3 zeigt auf Laufwerks-Port
 move.l  a2,-(a7)                 ;A2 retten
 move.l  78(a3),a2                ;Zeiger auf Load Puffer
 moveq   #1,d0                    ;Wert fÜr Motor an
 bsr     motorschalten            ;Motor einschalten
 moveq   #0,d0                    ;D0 löschen, da Wort-Operation
 move.w  74(a3),d0                ;Tracknummer nach D0
 bsr     movehead                 ;Schreib-Lesekopf positionieren
 lea     1668(a2),a0              ;Zeiger auf Anfang der Daten
 move.w  #14716,d0                ;Anzahl zu lesender Bytes
 bsr     read                     ;Track lesen
 tst.l   d0                       ;Fehler beim Lesen?
 beq     noerror                  ;Nein, dann verzweigen
 move.b  d0,3(a2)                 ;sonst Fehlernummer Übergeben
 bra     readexit                 ;und Routine verlassen
noerror:
 bsr     findsync                 ;Track richtigstellen und LÜcke entfernen
 move.b  d0,3(a2)                 ;Sektornummer eintragen
readexit:
 move.l  (a7)+,a2                 ;A2 zurÜckholen
 rts                              ;RÜcksprung     

read:
;Einlesen eines Tracks von Diskette
;A0 Zeiger auf richtige Position im Load Puffer
;D0 enthält Anzahl zu lesender Bytes
 lea     setdsklen,a1             ;Zeiger auf Routine, die DSKLEN setzt
 movem.l a4/a2/d2,-(a7)           ;Register retten
 move.l  a0,a2                    ;Ladeadresse in A2
 move.l  d0,d2                    ;Anzahl zu lesender Bytes
 move.l  a1,a4                    ;Zeiger auf DSKLEN-Routine
 bsr     anmelden                 ;Laufwerk anmelden
 move.b  65(a3),$bfd100           ;Motorbits setzen
 move.w  #$4000,$dff024           ;DSKLEN-Register vorbereiten
 move.l  #1000,d0                 ;Wert fÜr Warteschleife
 bsr     warten                   ;warten
 lea     $dff000,a1               ;Zeiger auf Hardware-Register
 move.l  a2,32(a1)                ;Zeiger auf Puffer fÜr gelesene Daten
 move.w  #$1002,156(a1)           ;Sync-Interrupt sperren
 move.w  #$8002,154(a1)           ;Disk-Block-Ready Interrupt freigeben
 btst    #2,$bfe001               ;Diskette im Laufwerk?
 bne     diskinserted             ;Ja, dann verzweige
diskremoved:
 moveq   #29,d0                   ;Fehlermeldung: keine Disk eingelegt
 bra     diskerror                ;Routine verlassen
diskinserted:
 lsr.w   #1,d2                    ;Anzahl Bytes in Anzahl Worte wandeln
 ori.w   #$8000,d2                ;DMA-Bit setzen
 move.l  d2,d0                    ;Wert nach D0
 jsr     (a4)                     ;DSKLEN-Routine aufrufen
 bsr     waitmessage              ;Auf RÜckmeldung warten
 lea     $dff000,a1               ;Zeiger auf Hardware-Register
 move.w  #2,154(a1)               ;Disk-Block-Ready Interrupt sperren
 move.w  #$4000,36(a1)            ;Disk-DMA sperren
 btst    #2,$bfe001               ;Disk herausgenommen?
 beq     diskremoved              ;Ja, Fehlermeldung
 moveq   #0,d2                    ;Fehler-Flag auf OK
diskerror:
 bsr     abmelden                 ;Laufwerk abmelden
 move.l  d2,d0                    ;RÜckmeldung nach D0
 movem.l (a7)+,a4/a2/d2           ;Register zurÜckholen
 rts                              ;RÜcksprung

findsync:
;Diese Routine sucht nach der Standard-Sync-Markierung ($4489) und stellt
;ggf. die Daten im Speicher richtig.
;A3 zeigt auf den Laufwerks-Port
;A6 zeigt auf die Trackdisk-Device-Struktur
 movem.l a2/d2-d6,-(a7)           ;Register retten
 link    a4,#-8                   ;Eigener Stapel fÜr Zwischenspeicherungen
 move.l  78(a3),a2                ;Zeiger auf Load-Puffer (codierte Daten)
 lea     1664(a2),a2              ;Zeiger auf Anfang der Daten
 move.l  a2,a0                    ;Zeiger auf Daten in A0
 addq.l  #2,a0                    ;Anfangsmarkierung Überspringen
 move.l  #2748,d0                 ;zuviel gelesene Bytes als Zähler
 bsr     findheader               ;Block-Header suchen
 cmpa.l  #-1,a0                   ;Header gefunden?
 beq     nosyncfound              ;Nein, Fehler
 move.l  a0,d5                    ;Zeiger auf Sync nach D5
 move.l  d0,d2                    ;Anzahl der zu verschiebenden Bits
 addq.l  #8,a0                    ;Zeiger auf codiertes Header-Langwort
 tst.l   d2                       ;mÜssen Bits verschoben werden?
 bne     shiftheader              ;Ja
 move.l  (a0),-8(a4)              ;1. Langwort des codierten Headers
 move.l  4(a0),-4(a4)             ;2. Langwort des codierten Headers
 bra     examineheader            ;Header untersuchen
shiftheader:
 bsr     getrightlongword         ;Richtig geschobenen Header holen
 move.l  d0,-8(a4)                ;und speichern
 bsr     getrightlongword         ;zweites Langwort des Headers holen
 move.l  d0,-4(a4)                ;und speichern
examineheader:
 lea     -8(a4),a0                ;Zeiger auf gelesenen Header setzen
 bsr     decodelongword           ;Header-Langwort decodieren
 move.l  d0,d3                    ;decodierter Header nach D3
 moveq   #0,d0                    ;D0 löschen, da Byte-Operation
 move.b  d3,d0                    ;Anzahl Blöcke bis zur LÜcke
 mulu    #1088,d0                 ;Anzahl Bytes bis zur LÜcke
 move.l  d5,a0                    ;Zeiger auf Sync-Markierung
 move.l  a2,a1                    ;zeigt auf Anfang der Daten im Load Puffer
 move.l  d2,d1                    ;Anzahl der zu verschiebenden Bits
 move.l  d0,d4                    ;Byte-Entfernung bis zur LÜcke in D4
 bsr     shiftblocks              ;Daten zurechtkopieren
 moveq   #0,d2                    ;D2 löschen, da Byte-Operation
 move.b  d3,d2                    ;Anzahl Blöcke bis zur LÜcke
 sub.l   #11,d2                   ;maximal 11 Blöcke pro Track
 neg.l   d2                       ;Anzahl der Blöcke nach der LÜcke
 beq     nomoreblocks             ;dies ist der Block vor der LÜcke
 add.l   d4,d5                    ;Adresse der LÜcke bestimmen
 move.l  #1160,d0                 ;Anzahl der zu durchsuchenden Byte
 move.l  d5,a0                    ;Zeiger auf LÜcke in A0
 addq.l  #2,a0                    ;Anfangsmarkierung Überspringen
 bsr     findheader               ;Standard-Sync nach LÜcke suchen
 cmpa.l  #-1,a0                   ;Sync gefunden?
 beq     nosyncfound              ;Nein, Fehler
 move.l  d0,d1                    ;Anzahl der zu verschiebenden Bits
 move.l  a2,a1                    ;zeigt auf Anfang der Daten im Load Puffer
 adda.l  d4,a1                    ;Zieladresse fÜr Daten
 move.l  d2,d0                    ;Anzahl der Blöcke nach LÜcke
 mulu    #1088,d0                 ;Anzahl Bytes nach LÜcke
 bsr     shiftblocks              ;Daten zurechtkopieren
nomoreblocks:
 move.l  a2,a0                    ;Zeiger auf Daten im Load Puffer
 adda.l  d4,a0                    ;Adresse der neu kopierten Daten
 bsr     connect                  ;Ränder korrigieren
 lea     11968(a2),a0             ;Zeiger auf Ende der Daten
 move.w  #$aaa8,d0                ;Wert fÜr Endmarkierung
 btst    #0,-1(a0)                ;letztes Datenbit testen
 beq     bitgelöscht              ;schon gelöscht
 bclr    #15,d0                   ;sonst Endmarkierungsbit löschen
bitgelöscht:
 move.w  #$aaaa,(a2)              ;Anfangsmarkierung eintragen
nosyncfound:
 unlk    a4                       ;Zwischenspeicher freigeben
 movem.l (a7)+,a2/d2-d6           ;Register zurÜckholen
 rts                              ;RÜcksprung

findheader:
;Sucht nach Standard-Sync-Markierung ($4489) im Block-Header
;A0 zeigt auf die zu decodierenden Daten
;D0 enthält Anzahl zu durchsuchender Bytes
 movem.l a2/d2-d4,-(a7)           ;Register retten
 move.w  #$aaaa,d3                ;erstes Kontrollwort in D3
 move.w  #$5555,d4                ;zweites Kontrollwort in D4
 move.l  a0,a2                    ;Zeiger auf Daten nach A2
 adda.l  d0,a2                    ;Zeiger auf Ende der Daten
findloop:
 move.w  (a0)+,d2                 ;aktuelles Wort in D2
 cmp.w   d3,d2                    ;Datenbit am Anfang?
 beq     databitfound             ;Ja
 cmp.w   d4,d2                    ;Taktbit am Anfang?
 beq     taktbitfound             ;Ja
 cmpa.l  a0,a2                    ;Ende der Daten erreicht?
 bhi     findloop                 ;Nein, weitersuchen
notfound:
 moveq   #-1,d0                   ;Fehlermeldung in D0
 move.l  d0,a0                    ;Adresse auf Daten löschen
 bra     nosync                   ;keine Sync-Markierung gefunden
taktbitfound:
 moveq   #15,d0                   ;Zähler fÜr Anzahl der verschobenen Bits
 lea     takttabelle,a1           ;Zeiger auf Tabelle in A1
nullmarke:
 cmpa.l  a0,a2                    ;Ende der Daten erreicht?
 bls     notfound                 ;Ja, Fehler
 move.w  (a0)+,d1                 ;nächstes Wort nach D1
 cmp.w   d2,d1                    ;immer noch Kennung vor Sync-Markierung?
 beq     nullmarke                ;Ja, nächstes Wort untersuchen
 subq.l  #2,a0                    ;Zeigt nun auf vorheriges Wort
 move.l  (a0),d1                  ;Langwort in D1
testsync:
 cmp.l   (a1)+,d1                 ;Sync-Markierung in D1?
 beq     syncfound                ;Ja, mögliche Sync ($4489) in D1
 subq    #2,d0                    ;sonst Anzahl der verschobenen Bits
                                  ;verringern
 bge     testsync                 ;solange D0>0, weitertesten
 bra     findloop                 ;dies war keine Sync, also weitersuchen
syncfound:
 subq.l  #4,a0                    ;Zeigt auf Sync-Markierung
nosync:
 movem.l (a7)+,a2/d2-d4           ;Register zurÜckholen
 rts                              ;RÜcksprung
databitfound:
 moveq   #14,d0                   ;Zähler fÜr Anzahl der verschobenen Bits
 lea     datatabelle,a1           ;Zeiger auf Tabelle setzen
 bra     nullmarke                ;Sync-Markierung suchen

shiftblocks:
;Diese Routine kopiert die Daten an die Stelle im Load Puffer, an der die
;sinnvollen Daten beginnen (Offset 1664). Falls die Daten verschoben sein
;sollten, werden sie zurechtgerÜckt.
;A0 zeigt auf Syncadresse eines Blocks
;A1 zeigt auf Ziel fÜr die richtigen Daten (Offset 1664 im Load Puffer)
;A3 zeigt auf den Laufwerks-Port
;A6 zeigt auf Trackdisk-Device-Struktur
;D0 enthält die Anzahl der zu bearbeitenden Bytes
;D1 enthält die Anzahl Bits, um die verschoben werden muß
 link    a2,#-30                  ;Platz fÜr QBLIT-Struktur
 move.b  d1,-8(a2)                ;Anzahl der Verschiebungsbits eintragen
 tst.l   d1                       ;mÜssen Bits verschoben werden?
 beq     noshift                  ;Nein
 addq.l  #2,d0                    ;sonst ein Wort von Ende einschieben
noshift:
 move.l  d0,d1                    ;Wert fÜr
 add.l   #63,d1                   ;BLTSIZE berechnen
 and.w   #$ffc0,d1                ;Breite des Blitterfensters auf Null
 or.w    #32,d1                   ;Breite setzen
 move.w  d1,-10(a2)               ;BLTSIZE in QBLIT-Struktur eintragen
 movem.l d0/a0/a1,-22(a2)         ;Werte in Struktur eintragen
 move.l  #shiftroutine1,-26(a2)   ;Zeiger auf Funktion sezten
 move.l  a3,-4(a2)                ;Laufwerks-Port eintragen
 lea     -30(a2),a1               ;Zeiger auf Anfang der Struktur
 move.l  a6,-(a7)                 ;A6 retten
 move.l  56(a6),a6                ;Zeiger auf GfxBase
 jsr     qblit(a6)                ;QBLIT-Funktion aufrufen
 move.l  (a7)+,a6                 ;A6 zurÜckholen
 bsr     waitmessage              ;Auf Reply-Message warten
 unlk    a2                       ;Platz fÜr QBLIT-Struktur freigeben
 rts                              ;RÜcksprung

shiftroutine1:
;evtl. lea $dff000,a0
 move.l  a5,-(a7)                 ;A5 retten
 move.l  a1,a5                    ;Zeiger auf QBLIT-Struktur
 bsr     setmodulo                ;Blitter-Parameter setzen
 move.b  22(a5),d0                ;Anzahl der Verschiebungsbits
 moveq   #12,d1                   ;Verschiebungswert ins oberste Nibble
 lsl.w   d1,d0                    ;Wert nun in Bits 15-12
 move.w  #$5cc,64(a0)             ;BLTCON0 beschreiben
                                   ;keine Verschiebung fÜr A
                                   ;DMA-Bits fÜr B und D
                                   ;ABC+ABc+aBC+aBc als Minterms (D=B)
 move.w  d0,66(a0)                ;BLTCON1 beschreiben (Verschiebung von B)
 movem.l 8(a5),d0/d1/a1           ;Werte aus Struktur holen
 move.l  #shiftroutine2,4(a5)     ;Zeiger auf nächste Funktion
 tst.b   22(a5)                   ;Verschiebung notwendig?
 beq     keineverschiebung        ;Nein, dann verzweige
 subw.l  #2,a1                    ;Einschub am Ende unnötig
 move.l  #shiftroutine3,4(a5)     ;Zeiger auf nächste Funktion
keineverschiebung:
 move.l  a1,84(a0)                ;Zeiger auf Destination D
 move.w  (a1),24(a5)              ;erstes Wort in QBLIT-Struktur speichern
 move.w  20(a5),88(a0)            ;BLTSIZE beschreiben (Blitter starten)
 move.l  (a7)+,a5                 ;A5 zurÜckholen
 rts                              ;RÜcksprung

shiftroutine3:
 move.l  16(a1),a0                ;Zeiger auf Ziel in A0
 move.w  24(a1),-2(a0)            ;Zwischengespeichertes Wort zurÜckschreiben
shiftroutine2:
 moveq   #0,d0                    ;D0 löschen
 move.l  d0,4(a1)                 ;Funktionszeiger löschen
 move.l  26(a1),a1                ;Zeiger auf Laufwerks-Port in A1
 bsr     sendmessage              ;Message fÜr Ende senden
 moveq   #0,d0                    ;Flag fÜr Ende
 rts                              ;RÜcksprung

decodelongword:
;Decodiert ein Langword aus zwei hintereinander stehenden MFM-Langworten
;A0 zeigt auf erstes MFM-Langword
;D0 gibt decodiertes Langwort zurÜck
 move.l  (a0)+,d0                 ;Erstes Langwort holen
 move.l  (a0)+,d1                 ;Zweites Langwort holen
 and.l   #$55555555,d0            ;Taktbits entfernen
 and.l   #$55555555,d1            ;Taktbits entfernen
 lsl.l   #1,d0                    ;Bits richtigstellen
 or.l    d1,d0                    ;und verknÜpfen
 rts                              ;RÜcksprung

getrightlongword:
;Diese Routine schiebt ein codiertes Langwort richtig
;A0 zeigt auf auf das Langwort
;D2 enthält Anzahl Bits fÜr die Verschiebung
;D0 gibt geschobenes Langwort zurÜck
 move.l  (a0)+,d0                 ;Langwort holen
 move.w  (a0),d1                  ;nachfolgendes Wort auch, da maximale
                                  ;Verschiebung 15 Bit beträgt
 moveq   #16,d3                   ;max. Verschiebung + 1
 sub.l   d2,d3                    ;Verschiebung fÜr Langwort
 lsl.l   d3,d0                    ;Langwort richtig verschieben
 lsr.w   d2,d1                    ;Rest andersrum verschieben
 or.w    d1,d0                    ;ergibt richtiges Langwort
 rts                              ;RÜcksprung

takttabelle:
 dc.l $2244a244,$48912891,$52244a24,$54891289
 dc.l $552244a2,$55489128,$5552244a,$55548912
datatabelle:
 dc.l $91225122,$a4489448,$a9122512,$aa448944
 dc.l $aa912251,$aaa44894,$aaa91225,$44894489
