execbase = 4
putmsg = -366
getmsg = -372
findname = -276
wait = -318
qblit = -276
header = $ff150802

run:
 lea     quelle,a0            ;Zeiger auf Quelle
 lea     run,a1               ;Zeiger auf eigenes Programm
 move.l  #127,d0              ;128 Langwörter kopieren
copyloop:
 move.l  (a1)+,(a0)+          ;Programm als Quelle (Inhalt des Datenblocks)
 dbf     d0,copyloop          ;insgesamt 512 Bytes
 move.l  execbase,a6          ;Zeiger auf Execbase
 lea     trdname,a1           ;Zeiger auf Device-Name
 lea     350(a6),a0           ;Zeiger auf Device-List
 jsr     findname(a6)         ;Device finden
 tst.l   d0                   ;gefunden ?
 beq     notfound             ;Nein, ende
 move.l  276(a6),a0           ;Zeiger auf eigenen Task
 move.l  d0,a6                ;Device-Struktur in A6
 move.l  36(a6),a3            ;Zeiger auf Laufwerk-Port (df0:)
 lea     174(a3),a1           ;Adresse des Reply-Ports
 move.l  16(a1),-(a7)         ;Zeiger auf Empfänger-Task retten
 move.l  a1,-(a7)             ;Reply-Port retten
 move.l  a0,16(a1)            ;eigenen Task als Empfänger eintragen
 bset    #0,34(a3)            ;Trackdisk-Task auf Warteposition setzen
 move.l  #header,d0           ;Block-Header in D0
 lea     quelle,a0            ;Zeiger auf Quelle in A0
 lea     ziel,a1              ;Zeiger auf Ziel in A1
 jsr     blockcodierung       ;Block codieren
 move.l  (a7)+,a1             ;Replyport zurÜckholen
 move.l  (a7)+,16(a1)         ;alten Empfänger-Task wieder setzen
 bclr    #0,34(a3)            ;Trackdisk-Task wieder freigeben
notfound:
 rts                          ;Fertig

blockcodierung:
;A0 Zeiger auf zu codierenden Block (Quelle)
;A1 Zeiger auf Puffer fÜr codierte Daten (Ziel)
;A3 Zeiger auf Message-Port des Lauferks
;A6 Zeiger auf Trackdisk-Device-Struktur
;D0 enthält den uncodierten Informationsteil des Block-Headers
 movem.l a2/a4/d2,-(a7)      ;Register retten
 move.l  a1,a4               ;Zeiger auf Ziel nach A4 kopieren
 move.l  a0,a2               ;Zeiger auf Quelle nach A2 kopieren
 move.l  d0,d2               ;Block-Header nach D2 kopieren
 moveq   #0,d0               ;D0 löschen
 lea     (a4),a0             ;A0 zeigt auf Quelle
 bsr     codlongword         ;Nullbytes codieren und in Puffer schreiben
 move.l  #$44894489,4(a4)    ;Sync-Markierungen eintragen
 move.l  d2,d0               ;Block-Header wieder nach D0
 lea     8(a4),a0            ;Zeiger auf Quelle
 bsr     codlongword         ;Block-Header codieren und eintragen
 moveq   #3,d2               ;Zähler auf 3 setzen
nullcod:
 moveq   #0,d0               ;Nullbytes
 bsr     codlongword         ;4 Nullbytes codieren und eintragen
 dbf     d2,nullcod          ;Das Ganze 4 mal => 16 Nullbytes
 lea     8(a4),a0            ;A0 zeigt auf codierten Block-Header
 moveq   #40,d1              ;40 Bytes fÜr PrÜfsumme
 bsr     psumme              ;BlockprÜfsumme berechnen
 lea     48(a4),a0           ;Position der PrÜfsumme
 bsr     codlongword         ;PrÜfsumme codieren und eintragen
 move.l  #512,d0             ;Anzahl Bytes im Datenblock
 move.l  a2,a0               ;Zeiger auf Datenpuffer
 lea     64(a4),a1           ;Zeiger im Zielpuffer setzen
 bsr     coddatablock        ;Datenblock codieren
 lea     64(a4),a1           ;Zeiger auf Anfang der codierten Daten
 move.w  #1024,d1            ;1024 Bytes fÜr PrÜfsumme
 bsr     psumme              ;PrÜfsumme der Daten berechnen
 lea     56(a4),a0           ;Position der PrÜfsumme
 bsr     codlongword         ;PrÜfsumme codieren und eintragen
 movem.l (a7)+,a4/a2/d2      ;Register zurÜckholen
 rts                         ;Fertig

codlongword:
;D0 enthält das zu codierende Langwort
;A0 zeigt auf den Speicherbereich, in den die zwei codierten Langwörter
;hineingeschrieben werden.
 movem.l d2-d3,-(a7)         ;D2 und D3 retten
 move.l  d0,d3               ;Langwort nach D3 kopieren
 lsr.l   #1,d0               ;Einmal nach rechts verschieben
 bsr     codiere             ;ungerade Bits codieren und eintragen
 move.l  d3,d0               ;Langwort wieder in D0
 bsr     codiere             ;gerade Bits codieren und eintragen
 bsr     connect             ;Taktbit des nächsten Wertes berichtigen
 movem.l (a7)+,d2-d3         ;Register zurÜckholen
 rts                         ;Fertig

codiere:
;Diese Routine wird selbstständig aufgerufen und normalerweise nicht
;direkt vom Programmierer benutzt.
;D0 enthält das zu codierende Langwort
;A0 zeigt auf die Adresse, an der das codierte Langwort geschrieben wird
 and.l   #$55555555,d0       ;ungerade Bits (Taktbits) entfernen
 move.l  d0,d2               ;Ergebnis zwischenspeichern
 eor.l   #$55555555,d2       ;gerade Bits (Datenbits) umdrehen
 move.l  d2,d1               ;Ergebnis nach D1
 lsl.l   #1,d2               ;Einmal nach links verschieben
 lsr.l   #1,d1               ;Einmal nach rechts verschieben
 bset    #31,d1              ;vorderstes Bit setzen
 and.l   d2,d1               ;VerknÜpfen, um Taktbits herauszusuchen
 or.l    d1,d0               ;Taktbits setzen
 btst    #0,-1(a0)           ;Hat vorheriges Ergebnis Nullbit am Anfang?
 beq     bitok               ;Ja, Bits stehen richtig
 bclr    #31,d0              ;sonst vorderstes Bit löschen
bitok:
 move.l  d0,(a0)+            ;Wert eintragen
 rts                         ;RÜcksprung

connect:
;Diese Routine wird selbstständig aufgerufen und normalerweise nicht
;direkt vom Programmierer benutzt.
;A0 zeigt auf das nachfolgende Byte
 move.b  (a0),d0             ;Byte holen
 btst    #0,-1(a0)           ;erstes Datenbit (Bit 0) des vorherigen
                             ;Wertes gesetzt?
 bne     deletebit           ;Ja, dann Taktbit löschen
 btst    #6,d0               ;letztes Datenbit (Bit 30) prÜfen
 bne     bitsok              ;wenn gesetzt, dann alles OK
 bset    #7,d0               ;sonst letztes Taktbit (Bit 31) setzen
 bra     eintragen           ;korrigierten Wert zurÜckschreiben
deletebit:
 bclr    #7,d0               ;Taktbit löschen
eintragen:
 move.b  d0,(a0)             ;Wert zurÜckschreiben
bitsok:
 rts                         ;RÜcksprung

coddatablock:
;A0 zeigt auf den Datenpuffer (Quelle)
;A1 zeigt auf den Zielpuffer
;A3 zeigt auf den Laufwerks-Port
;A6 zeigt auf die Device-Struktur
;D0 enthält die Anzahl Daten, die codiert werden sollen
 link    a2,#-30             ;Platz fÜr QBLIT-Struktur. A2 zeigt nun
                             ;auf das Ende der Struktur
 move.w  d0,d1               ;Anzahl Daten nach D1 kopieren
 lsl.w   #2,d1               ;durch 4 teilen
 ori.w   #8,d1               ;BLTSIZE-Registerinhalt bestimmen
 move.w  d1,-10(a2)          ;und in Struktur eintragen
 movem.l a1/a0/d0,-22(a2)    ;Datenlänge, Quelle und Ziel eintragen
 move.l  #qbroutine,-26(a2)  ;Zeiger auf auszufÜhrendes Programm setzen
 move.l  a3,-4(a2)           ;Zeiger auf Laufwerks-Port eintragen
 lea     -30(a2),a1          ;A1 zeigt auf Anfang der Struktur
 move.l  a6,-(a7)            ;A6 speichern
 move.l  56(a6),a6           ;Zeiger auf GfxBase in A6
 jsr     qblit(a6)           ;QBLIT aufrufen
 move.l  (a7)+,a6            ;A6 zurÜckholen
 bsr     waitmessage         ;Auf Reply-Message warten
 movem.l -22(a2),a1/a0/d0    ;Register zurÜckholen
 move.l  d0,d1               ;Anzahl der Bytes nach D1
 move.l  a1,a0               ;Zeiger auf Anfang der Daten setzen
 bsr     connect             ;Rand korrigieren
 adda.l  d1,a0               ;Zeiger auf nächste Nahtstelle
 bsr     connect             ;Rand korrigieren
 adda.l  d1,a0               ;Zeiger auf Ende
 bsr     connect             ;Rand korrigieren
 unlk    a2                  ;Platz der Struktur wieder freigeben
 rts                         ;RÜcksprung

qbroutine:
;Dies ist die Routine, die von der QBLIT-Funktion angesprungen wird
;A0 zeigt auf $DFF000
;A1 zeigt auf die zuvor erstellte Struktur
;A6 zeigt auf die Trackdisk-Device-Struktur
 move.l  a5,-(a7)            ;A5 retten
 move.l  a1,a5               ;Zeiger auf Struktur kopieren
 bsr     setmodulo           ;Blitterparameter setzen
 move.l  a5,a1               ;A1 zurÜckholen
 movem.l 8(a1),a5/d1/d0      ;Zeiger auf Quelle und Ziel holen
 move.l  d1,76(a0)           ;Quelle nach BLTBPT (Source A)
 move.l  d1,80(a0)           ;sowie nach BLTAPT (Source B)
 move.l  a5,84(a0)           ;Ziel nach BLTDPT (Destination D)
 move.w  #$1db1,64(a0)       ;Wert fÜr BLTCON0 (Area Modus)
                              ;DMA-Bits fÜr A,B,D
                              ;Verschiebung um 1 nach rechts fÜr A
                              ;ABC+AbC+Abc+abc als Minterm
 move.w  #0,66(a0)           ;Wert fÜr BLTCON1 (Area Modus)
 move.w  20(a1),88(a0)       ;BLTSIZE beschreiben (Blitter starten)
 move.l  #qbroutine2,4(a1)   ;Zeiger auf nächste Funktion, die nach
                             ;dieser ausgefÜhrt werden soll
 move.l  (a7)+,a5            ;A5 zurÜckholen
 rts                         ;RÜcksprung

qbroutine2:
;Diese Routine wird aufgerufen, wenn der Blit-Vorgang der ersten Funktion
;beendet ist. Die Parameter sind, wie bei den folgenden Routinen, gleich.
 move.l  a5,-(a7)            ;A5 retten
 movem.l 8(a1),a5/d1/d0      ;Werte aus der Struktur holen
 move.l  a5,76(a0)           ;Source B = Ziel
 move.l  d1,80(a0)           ;Source A = Quelle
 move.l  a5,84(a0)           ;Destination D = Ziel
 move.w  #$2d8c,64(a0)       ;Wert fÜr BLTCON0
                              ;DMA-Bits fÜr A,B,D
                              ;Verschiebung um 2 nach rechts fÜr A
                              ;ABC+aBC+aBc als Minterm
 move.w  20(a1),88(a0)       ;BLTSIZE beschreiben (Blitter starten)
 move.l  #qbroutine3,4(a1)   ;Zeiger auf nächste Funktion
 move.l  (a7)+,a5            ;A5 zurÜckholen
 rts                         ;RÜcksprung

qbroutine3:
 move.l  a5,-(a7)            ;A5 retten
 movem.l 8(a1),a5/d1/d0      ;Werte aus der Struktur holen
 add.l   d0,d1               ;Zeiger auf Ende der Quelle
 subq.l  #2,d1               ;Ende -2
 adda.l  d0,a5               ;Zeiger auf Ende
 adda.l  d0,a5               ;des Ziels setzen
 subq.l  #2,a5               ;Ende -2
 move.l  d1,76(a0)           ;Source B zeigt auf Ende der Quelle
 move.l  d1,80(a0)           ;Source A zeigt auf Ende der Quelle
 move.l  a5,84(a0)           ;Destination D zeigt auf Ende des Ziels
 move.w  #$0db1,64(a0)       ;Wert fÜr BLTCON0
                              ;DMA-Bits fÜr A,B,D
                              ;keine Verschiebung
                              ;ABC+AbC+Abc+abc als Minterm
 move.w  #$1002,66(a0)       ;Wert fÜr BLTCON1
                              ;Verschiebung um 1 fÜr B
                              ;Descent-Mode (Vom Ende zum Anfang)
 move.w  20(a1),88(a0)       ;BLTSIZE beschreiben (Blitter starten)
 move.l  #qbroutine4,4(a1)   ;Zeiger auf nächste Funktion
 move.l  (a7)+,a5            ;A5 zurÜckholen
 rts                         ;RÜcksprung

qbroutine4:
 move.l  a5,-(a7)            ;A5 retten
 movem.l 8(a1),a5/d1/d0      ;Werte aus der Struktur holen
 adda.l  d0,a5               ;Zeiger auf Ende des ersten Teils vom Ziel
 move.l  a5,76(a0)           ;als Source B eintragen
 move.l  d1,80(a0)           ;Source A = Quelle
 move.l  a5,84(a0)           ;Destination D = Ende des ersten Teil vom Ziel
 move.w  #$1d8c,64(a0)       ;Wert fÜr BLTCON0
                              ;DMA-Bits fÜr A,B,D
                              ;Verschiebung um 1 nach rechts fÜr A
                              ;ABC+aBC+aBc als Minterm
 move.w  #0,66(a0)           ;Wert fÜr BLTCON0
 move.w  20(a1),88(a0)       ;BLTSIZE beschreiben (Blitter starten)
 move.l  #qbroutine5,4(a1)   ;Zeiger auf nächste Funktion
 move.l  (a7)+,a5            ;A5 zurÜckholen
 rts                         ;RÜcksprung

qbroutine5:
 moveq   #0,d0               ;D0 löschen (=> keine weitere Funktion)
 move.l  d0,4(a1)            ;Funktionszeiger löschen
 move.l  26(a1),a1           ;Zeiger auf Laufwerks-Port holen
 bsr     sendmessage         ;Message fÜr Blit-Ende senden
 moveq   #0,d0               ;Flag fÜr Aussprung aus QBLIT-Funktion
 rts                         ;RÜcksprung

setmodulo:
;Diese Routine setzt die Modulo-Register und die Masken fÜr das erste und
;letzte Wort
 moveq   #0,d0               ;D0 löschen
 lea     68(a0),a1           ;Zeiger auf BLTAFWM
 move.l  #-1,(a1)            ;BLTAFWM und BLTALWM setzen
 lea     98(a0),a1           ;Zeiger auf BLTBMOD
 move.l  d0,(a1)+            ;BLTBMOD und BLTAMOD löschen
 move.w  d0,(a1)+            ;BLTDMOD löschen
 addq.l  #8,a1               ;Zeiger auf BLTCDAT setzen
 move.w  #$5555,(a1)         ;BLTCDAT setzen
 rts                         ;RÜcksprung

sendmessage:
;Diese Routine sendet die RÜckmeldung zum Beenden des Wartevorgangs
;A1 zeigt auf den Laufwerks-Port
;A6 zeigt auf die Trackdisk-Device-Struktur
 lea     174(a1),a0          ;Zeiger auf Reply-Port
 lea     94(a1),a1           ;Zeiger auf Reply-Message
 move.l  a6,-(a7)            ;A6 retten
 move.l  execbase,a6         ;Zeiger auf Execbase
 jsr     putmsg(a6)          ;Message senden
 move.l  (a7)+,a6            ;A6 zurÜckholen
 rts                         ;RÜcksprung

waitmessage:
;Diese Routine wartet, bis eine Message zum Reply-Port gesandt wird
;A3 zeigt auf den Laufwerks-Port
;A6 zeigt auf die Trackdisk-Device-Struktur
 move.l  #$400,d0            ;SignalSet als Parameter der WAIT-Funktion
 move.l  a6,-(a7)            ;A6 retten
 move.l  execbase,a6         ;Zeiger auf Exexbase
 jsr     wait(a6)            ;Task in Warte-Status setzen
 move.l  (a7)+,a6            ;A6 zurÜckholen
 lea     174(a3),a0          ;Zeiger auf Reply-Port
 move.l  a6,-(a7)            ;A6 retten
 move.l  execbase,a6         ;Zeiger auf Execbase
 jsr     getmsg(a6)          ;Message holen
 move.l  (a7)+,a6            ;A6 zurÜckholen
 tst.l   d0                  ;Message angekommen?
 beq     waitmessage         ;Nein, weiter warten
 rts                         ;RÜcksprung

psumme:
;Berechnet die PrÜfsumme (Byteanzahl muß durch 4 teilbar sein !!!)
;A0 zeigt auf die Daten, deren PrÜfsumme berechnet werden soll
;D1 enthält die Anzahl der Daten in Bytes
 move.l  d2,-(a7)            ;D2 retten
 lsr.w   #2,d1               ;Byteanzahl durch 4 teilen
 subq.w  #1,d1               ;wegen dbf
 moveq   #0,d0               ;Ergebnis auf Null setzen
pmarke:
 move.l  (a0)+,d2            ;Langwort holen
 eor.l   d2,d0               ;und verknÜpfen
 dbf     d1,pmarke           ;bis zum Ende
 and.l   #$55555555,d0       ;ungÜltige Bits entfernen
 move.l  (a7)+,d2            ;D2 zurÜckholen
 rts                         ;RÜcksprung

trdname: dc.b "trackdisk.device",0
even
quelle: blk.b 512,0
ziel: blk.b 1090,0
