;The Listing of the Copy Program
key            = $BFEC01
Cont           = $BFEE01
IntCon         = $BFED01
MaxWait        = $4000
MinWait        = $1000
;
;------- graphics.library ------
;
Textout              = -30 - 30
InitRastPort         = -30 -168
Movee                = -30 -210
Draw                 = -30 -216
RectFill             = -30 -276
SetAPen              = -30 -312
InitBitMap           = -30 -360
;
;--------- exec.library --------
;
ExecBase             =        4
;
AllocMem             = -30 -168
AvailMem             = -216
FreeMem              = -30 -180
OldOpenLibrary       = -30 -378
CloseLibrary         = -30 -384
FindName             = -276
;
MEMF_Chip            = $02
MEMF_Fast            = $04
MEMF_Largest         = $20000

DevList              = 350
Port                 = 36       ;Drive 0
IDNestCnt      = 294

;
;-------------------------------
;
floppy_size = floppyend - floppy

floppy_s       = floppy_size/6-1

ON             = 1
OFF            = 0

;Error-Flag Values

NoError        = $0000
NoSync         = $0001
LengthUnequal  = $0002
LengthUnequal2 = $0003
NoDisk         = $0004
ReadError      = $0005
VerifyError    = $0006
DiskProtect    = $0007
NotProtect     = $0008
Escape         = $0009

CopyAttempt1  = 3                  ;Attempts on illegal Data 
CopyAttempt2  = 3                  ;Attempts on NoSync

;Load options 

WithoutSync     = $0000
WithSync        = $ffff

;Write options

NoIndex        = $0000
IndexOk        = $ffff

;Size of memory used

SortBlockNum  = $40   ;Number of blocks,
                      ;whose length is sorted
Bytesread      = $3600
BSize          = 2*Bytesread
req            = 2        ;Chip-Memory
CIAA           = $BFE000

GapLengthF    = $500 ;Length of Gap for FastCopy
NumReadsF      = 5   ;Number of Read attempts for Readerror (Fast)

;Values for Cruncher

ShrtNull       = $80
MiddleNull     = $20
LongNull       = $08
ShrtNorm       = $40
MiddleNorm     = $10
LongNorm       = $04
ShrtNone       = $c0
MiddleNone     = $30
LongNone       = $02
EmptyBlock     = $01


               lea DevName,a1
               move.l $4,a6
               lea DevList(a6),a0
               jsr FindName(a6)
               move.l d0,a0
               beq Ende
               lea Port(a0),a0
               clr.w d0
\An2:          tst.l (a0)+
               beq \An1
               bset d0,Drives
\An1:          addq.w #1,d0
               cmp.w #4,d0
               bne.s \An2
        move.l ExecBase,a6
        lea    gfxname,a1
        jsr    OldOpenLibrary(a6)
        move.l d0,gfxbase
        beq    no_gfxbase

        move.l #$2800,d0
        move.l #$10002,d1
        jsr    AllocMem(a6)
        move.l d0,bit_adress
        beq    no_bitmap

        move.l #copsize+2,d0
        move.l #$10002,d1
        jsr    AllocMem(a6)
        move.l d0,cop_adress
        beq    no_copper
               MOVE.L #BSize,D0
               MOVE.L #req,D1
               JSR AllocMem(A6)
               TST.L D0
               BEQ no_DPuffer
               MOVE.L D0,TrackBuffer1
               addq.l #6,TrackBuffer1
               add.l #Bytesread-6,d0
               move.l D0,TrackBuffer2
               bsr GetMemory           ;Memory for Cruncher

               bra beg
copy_start:    MOVE.L $4,A6
               MOVE.B #$FF,$BFD300
               move.w #$0020,$dff09a
               JSR Disable

               MOVE.W #$8210,$DF096      ;set DMA-Reg. 

               clr.w FreeFlagCh
               clr.w FreeFlagFa

               bsr HeadMov       ;set Heads to Null and set Motorbits 
               bsr Start_End     ;determine copy area 
               cmp.b #ON,dc1     ;Deepcopy 1
               beq \ME7
               cmp.b #ON,dc2
               bne \ME5
\ME7:          move.b SD,d0              ;one Drive-Copy?
               cmp.b DD,d0
               beq \ME6                  ;yes 
               bsr SwitchS
\ME5:          bsr TestProtect
               tst.l d0
               bmi \ME4
               bsr protect_source
               tst.l d0
               bmi \ME3                  ;Escape
               bra \ME5
\ME4:
               cmp.b #ON,fa              ;Fastcopy on?
               bne \ME1
               bsr FastCopy
               bra \ME3
\ME1:          cmp.b #ON,dc1             ;Deepcopy1 on?
               bne \ME2
               bsr DeepCopy
               bra \ME3
\ME2:          cmp.b #ON,dc2             ;Deepcopy2 on?
               bne \ME3
\ME6:          bsr DeepCopy
\ME3:
               bsr SwitchS
               bsr MotorOff
               bsr SwitchD
               bsr MotorOff

               move.w #$0600,$dff09e
               move.w #$8100,$dff09e     ;restore Bits
\Error:       bsr Enable
        move.w #$8020,$dff09a
Ende:          rts

TextoutL:      move.w StartTrack,d0
               lsr.w #1,d0
               move.b d0,Cylinder
               bsr reading_cyl
               rts
TextoutS:      move.w StartTrack,d0
               lsr.w #1,d0
               move.b d0,Cylinder
               bsr writing_cyl
               rts
;output Read-Error 
RError:        move.w StartTrack,d0
               move.b #1,side
               btst #0,d0
               bne \RE1
               clr.b side
\RE1:          lsr.w #1,d0
               move.b d0,Cylinder
               bsr read_error
               rts
;output Write-Error 
WError:        move.w StartTrack,d0
               move.b #1,side
               btst #0,d0
               bne \RE1
               clr.b side
\RE1:          lsr.w #1,d0
               move.b d0,Cylinder
               bsr write_error
               rts

FastCopy:
               bsr GapCreate
               move.b DD,d0
               cmp.b SD,d0
               beq \FC1
               bra FastCopyML            ;for several Drives
\FC1:          bra FastCopyEL            ;for one Drive

;FastCopy for several Drives
FastCopyML:
               bsr SwitchD
\FC5:          bsr TestProtect
               tst.l d0
               bpl \FC1
               bsr protect_Destination
               tst.l d0
               bmi \Error                ;Escape
               bra \FC5
\FC1:          bsr TextoutL
               bsr TrackLSF              ;load Track from Source 
               cmp.w #NoDisk,ErrorFlag
               beq \Error
               bsr SwitchD
               move.w StartTrack,d0
               bsr HeadPos
               bsr TextoutS
               bsr TrackFastWrite
               cmp.w #NoDisk,ErrorFlag
               beq \Error
               cmp.w #DiskProtect,ErrorFlag
               bne \FC3
               bsr protect_destination
               bra \Error
\FC3:          cmp.b #ON,vd              ;Verify ON ?
               bne \FC2                  ;branch if not on 
               bsr TrackFVerify
               cmp.w #NoDisk,ErrorFlag
               beq \Error
               cmp.w #VerifyError,ErrorFlag
               bne \FC2
               bsr WError
               bsr compare_drives
\FC2:          add.w #1,StartTrack
               move.w StartTrack,d0
               cmp.w EndTrack,d0
               bls \FC1
\Error        rts

;FastCopy for one Drive

FastCopyEL:
               clr.b ShrtByte            ;ShortByte for Chruncher = 0
               move.w #$1600,Length
               bsr NextMemory            ;assign memory
\FCEL1:        bsr TestProtect
               tst.l d0
               bmi \FCEL3
               bsr protect_Source
               tst.l d0
               bmi \FCEL2                ;Escape activated 
               bra \FCEL1
\FCEL3:        bsr FCopy1DL              ;read in memory
               tst.l d0
               bmi \FCEL2
               move.l WriteAddrs,a5
               add.l #GapLengthF,a5
\FCEL7:        move.w TNumBufferA,StartTrack
               bsr insert_destination
               tst.l d0
               bmi \FCEL2                ;Escape
\FCEL5:        bsr TestProtect
               tst.l d0
               bpl \FCEL6
               bsr protect_Destination
               tst.l d0
               bmi \FCEL2                ;Escape activated
               bra \FCEL5
\FCEL6:        bsr FCopy1DS              ;Write Tracks
               tst.l d0
               bmi \FCEL2
               cmp.b #ON,ws              ;write repeatedly ?
               bne \FCEL8                ;no 
               bsr write_b_again
               cmp.w #Escape,ErrorFlag
               beq \FCEL2
               tst.l d0
               bpl \FCEL7                ; write again 
\FCEL8:        move.w StartTrack,TNumBufferA
               move.w TNumBufferE,d0
               cmp.w EndTrack,d0
               bcc \FCEL2
               bsr insert_source
               tst.l d0
               bmi \FCEL2                ;Escape
               bra \FCEL1
\FCEL2:        rts

FCopy1DL:
\FCD1:         bsr TrackLSF              ;load Track from Source 
               cmp.w #NoDisk,ErrorFlag
               beq \Error
               move.l TrackBuffer2,a0    ;pass Pointer 
               bsr Packe                 ;crunch Track 
               tst.l d0
               bmi \FCD2                 ;memory full
               bsr TextoutL              ;output Text 
               add.w #1,StartTrack
               move.w StartTrack,d0
               cmp.w EndTrack,d0
               bls \FCD1
\FCD2:         subq.w #1,StartTrack
               clr.l d0
               move.w StartTrack,TNumBufferE       ;Last Track
               rts
\Error:       move.l #-1,d0
               rts

;Copy portion for writing with one Drive
FCopy1DS:
               move.w StartTrack,d0      ;first Track read
\FDS1:         bsr HeadPos
               bsr TextoutS
               move.l TrackBuffer2,a0    ;Buffer for Track (Target)
               bsr EntPacke              ;Track in regular size again
               move.l a5,a1              ;Target (TrackBuffer1 + Gap)
               move.l TrackBuffer2,a0    ;Source
               move.w StartTrack,d0      ;Track to be read
               bsr CodeTrack             ;code Track 
               move.w #00,FirstBlockSp   ;first Block = Null
               bsr TrackFastWrite
               cmp.w #NoDisk,ErrorFlag
               beq \Error
               cmp.w #DiskProtect,ErrorFlag
               bne \FDS3
               bsr protect_destination
               bra \Error
\FDS3:         cmp.b #ON,vd              ;Verify ON ?
               bne \FDS2                 ;branch if not on
               bsr TrackFVerify
               cmp.w #NoDisk,ErrorFlag
               beq \Error
               cmp.w #VerifyError,ErrorFlag
               bne \FDS2
               bsr WError
\FDS2:         bsr Get_Key               ;Escape activated?
               cmp.b #$45,d0
               bne \FCS4                 ;no, continue 
               move.w #Escape,ErrorFlag
               bra \Error
\FCS4:         addq.w #1,StartTrack
               move.w StartTrack,d0
               cmp.w TNumBufferE,d0
               bls \FDS1
               clr.l d0
               clr.w FreeFlagCh          ;Chip-Mem is available again 
               clr.w FreeFlagFa          ;Fast-Memomory is available again
               rts
\Error:       move.l #-1,d0
               rts

;crunch Track and store 
;>= A0 Pointer to TrackBuffer
Packe:                                   ;Pointer to Track
               move.l a2,-(a7)
               move.l a0,a2
\PA2:          lea TrackPointer,a0       ;Pointer to Track-Table
               clr.l d0
               move.w StartTrack,d0      ;Track-Number
               lsl.w #2,d0
               adda.l d0,a0              ;Pointer to Memory pointer
               move.l MemoryBeg,(a0)     ;store Pointer to Track
               move.l MemoryBeg,a1
               move.l a2,a0
               bsr Crunch
               tst.l d0
               bpl \PA1                  ;Ok, continue 
               bsr NextMemory            ;get new Mempory
               tst.l d0
               bpl \PA2                  ;Ok, Memory obtained
\PA1:          move.l (a7)+,a2
               rts

;get Track from memory
;>= A0 = Pointer to Target for Track
EntPacke:
               move.l a0,a1
               lea TrackPointer,a0       ;Pointer to Track-Table 
               clr.l d0
               move.w StartTrack,d0      ;Track-Number
               lsl.w #2,d0
               adda.l d0,a0              ;Pointer to memory pointer
               move.l (a0),a0            ;get Pointer to Track
               bsr DeCrunch
               rts

GetMemory:
               move.l a6,-(a7)
               move.l #MEMF_Chip,d1
               or.l #MEMF_Largest,d1
               move.l ExecBase,a6
               jsr AvailMem(a6)
               move.l d0,LengthChip
               bne \HS1
               clr.l MemoryChip          ;no Chip available
               bra \HS2                  ;get Fast-Memory 
\HS1:          jsr AllocMem(a6)
               move.l d0,MemoryChip
\HS2:          move.l #MEMF_Fast,d1
               or.l #MEMF_Largest,d1
               jsr AvailMem(a6)
               move.l d0,LenghtFast
               bne \HS3                  ;ok
               clr.l MemoryFast
               bra \HS4                  ;no fast memory available 
\HS3:          jsr AllocMem(a6)
               move.l d0,MemoryFast
\HS4:          move.l (a7)+,a6
               clr.w FreeFlagCh          ;memory is free
               clr.w FreeFlagFa
               rts

;get next memory block
NextMemory:
               tst.w FreeFlagCh          ;Chip not available 
               bpl \NS1                  ;Yes, is free 
\NS3:          tst.w FreeFlagFa          ;Fast memory still available 
               bpl \NS4                  ;Yes, is free 
\NS5:          move.l #-1,d0             ;no memory free 
               bra \NS2
\NS4:          move.l MemoryFast,d0
               beq \NS5                  ;no Fast memory free 
               move.l LenghtFast,d1
               move.w #$ffff,FreeFlagFa  ;Fast memory occupied 
               bra \NS6
\NS1:          move.l MemoryChip,d0
               beq \NS3                  ;no Chip free
               move.l LengthChip,d1
               move.w #$ffff,FreeFlagCh  ;occupy Chip 
\NS6:          move.l d0,MemoryBeg
               move.l d1,MemoryLength
               clr.l d0
\NS2:          rts

;load Track (Fastcopy)
;>= StartTrack = Track to be loaded 
;=> SBytes = Number of Bytes to be written 
;=> WriteAddrs = Address from which writing starts

TrackLSF:
               movem.l d2/a2,-(a7)
               bsr SwitchS
               move.l TrackBuffer1,a5
               move.l a5,WriteAddrs
               add.l #GapLengthF,a5
               move.l TrackBuffer2,a4
               move.w #(GapLengthF+$2ec0+2),SLength
               move.w StartTrack,d0
               bsr HeadPos
               move.w #NumReadsF-1,d2
\TSF6:         bsr FastReads
               move.w FirstBlock,FirstBlockSp  ;1. Block loaded
               cmp.w #NoDisk,ErrorFlag
               beq \TSF7
               cmp.w #ReadError,ErrorFlag
               bne \TSF5
               dbf d2,\TSF6        ;branch, if reading  again
               tst.l d0            ;No Sync found 
               bpl \TSF1
               move.l a4,a0              ;pass Buffer 
               bsr DOSClear              ;store Track empty 
\TSF1:
               bsr RError                ;output error 
               move.l a4,a0
               move.l a5,a1
               move.w StartTrack,d0      ;pass Track-Number
               bsr CodeTrack      ;generate Track from data 
               clr.w FirstBlockSp        ;first Block = 0
\TSF5:         clr.l d0
\TSF7:         movem.l (a7)+,d2/a2
               rts

;enter Gap Bytes in Track-Buffer 
GapCreate:
               move.l TrackBuffer1,a0
               move.w #(GapLengthF/4)+4,d0
\LS1:          move.l #$aaaaaaaa,(a0)+
               dbf d0,\LS1
               rts

TrackFVerify:
               movem.l d2-d4/a4-a5,-(a7)
               clr.w d3                ;Dest.-Counter
               clr.w VerErrFlag        ;erase Verify-Error-Flag
               move.b MotorBits,d4     ;store Motor Bits
\TF2:          move.l TrackBuffer2,a5
               move.l TrackBuffer1,a4
               add.l #GapLengthF,a4
\TF1:
               move.b tr,d2            ;number of Write attempts
               move.w d3,d1            ;Dest.-Number to D1
               bsr SwitchND            ;switch on Destination 
               tst.l d0                ;Drive present 
               bmi \TF6                ;No 
\TF4:          bsr FastVerify
               cmp.w #NoDisk,ErrorFlag
               beq \TF3                ;Error, No Disk
               cmp.w #VerifyError,ErrorFlag
               bne \TF6                ;no Error, continue
               subq.b #1,d2            ;decrement Error-Counter
               bne \TF5                ;continue if another attempt
               bset d3,VerErrFlag      ;set Bit for Error
\TF6:          addq.w #1,d3            ;increment Dest.number
               cmpi.w #4,d3
               bcs \TF1
               bra \TF3                ;no additional Drives
\TF5:          bsr TrackFastWrite
               bra \TF4
\TF3:          move.b d4,MotorBits
               movem.l (a7)+,d2-d4/a4-a5
               rts

TrackFastWrite:
               move.l a5,-(a7)
               move.l WriteAddrs,a5
               move.w SLength,d0
               move.w #NoIndex,d1
               bsr Writer
               move.l (a7)+,a5
               rts
DeepCopy:
               move.b DD,d0
               cmp.b SD,d0
               beq \DC1
               bra DeepCopyML          ;for several Drives
\DC1:          bra DeepCopyEL          ;for one Drive

DeepCopyEL:
               move.b #$aa,ShrtByte    ;ShortByte for Chruncher = aa
               bsr NextMemory          ;assign memory
               bsr insert_destination
               tst.l d0
               bmi \FCEL2
\FCEL9:        bsr TestProtect
               tst.l d0
               bpl \FCEL10
               bsr protect_Destination
               tst.l d0
               bmi \FCEL2              ;Escape activated
               bra \FCEL9
\FCEL10:       bsr LengthTest
               move.w StartTrack,TrackNumS
               move.w LenghtDest,d0    ;Length for Cruncher
               addi.w #$10,d0
               move.w d0,Length
\FCEL11:       bsr insert_source
               tst.l d0
               bmi \FCEL2
\FCEL1:        bsr TestProtect
               tst.l d0
               bmi \FCEL3
               bsr protect_Source
               tst.l d0
               bmi \FCEL2              ;Escape activated
               bra \FCEL1
\FCEL3:        bsr DeepCopy1DL         ;read into memory
               tst.l d0
               bmi \FCEL2
\FCEL7:        move.w TNumBufferA,StartTrack
               bsr insert_destination
               tst.l d0
               bmi \FCEL2
\FCEL5:        bsr TestProtect
               tst.l d0
               bpl \FCEL6
               bsr protect_Destination
               tst.l d0
               bmi \FCEL2              ;Escape activated
               bra \FCEL5
\FCEL6:        bsr DeepCopy1DS         ;Write Tracks
               tst.l d0
               bmi \FCEL2
               cmp.b #ON,ws            ;write several times ?
               bne \FCEL8              ;no
               bsr write_b_again
               cmp.w #Escape,ErrorFlag
               beq \FCEL2
               tst.l d0
               bpl \FCEL7              ; write again
\FCEL8:        move.w StartTrack,TNumBufferA
               move.w TNumBufferE,d0
               cmp.w EndTrack,d0
               bcs \FCEL11
\FCEL2:        rts

DeepCopy1DL:
\FCD1:         clr.w ErrorFlag
               bsr TrackLS             ;load Track from Source
               cmp.w #NoDisk,ErrorFlag
               beq \Error
               move.l TrackBuffer2,a0  ;pass Pointer
               move.l WriteAddrs,a1
               lea -6(a0),a0
               move.l a1,(a0)
               move.w SLength,4(a0)
               bsr Packe               ;crunch Track
               tst.l d0
               bmi \FCD2               ;Memory full
               bsr TextoutL
\FCD3:         add.w #1,StartTrack
               move.w StartTrack,d0
               cmp.w EndTrack,d0
               bls \FCD1
\FCD2:         subq.w #1,StartTrack
               clr.l d0
               move.w StartTrack,TNumBufferE       ;Last Track
               rts
\Error:       move.l #-1,d0
               rts

;Copy part for writing with one Drive
DeepCopy1DS:
               move.w StartTrack,d0    ;first Track read
\FDS1:         bsr HeadPos
               bsr TextoutS
               move.l TrackBuffer2,a0  ;Buffer for Track (Target)
               lea -6(a0),a0
               bsr EntPacke            ;Track again in normal size 
               move.l TrackBuffer2,a0
               move.l -6(a0),WriteAddrs
               move.w -2(a0),SLength
               move.l #$aaaaaaaa,-4(a0)
               bsr TrackWriter
               cmp.w #NoDisk,ErrorFlag
               beq \Error
               cmp.w #DiskProtect,ErrorFlag
               bne \FDS3
               bsr protect_destination
               bra \Error
\FDS3:         cmp.b #ON,vd            ;Verify ON ?
               bne \FDS2               ;branch, when not on
;               bsr TrackFVerify
;               cmp.w #NoDisk,ErrorFlag
;               beq \Error
;               cmp.w #VerifyError,ErrorFlag
;               bne \FDS2
;               bsr WError
\FDS2:         addq.w #1,StartTrack
               move.w StartTrack,d0
               cmp.w TNumBufferE,d0
               bls \FDS1
               clr.l d0
               clr.w FreeFlagCh        ;Chip-Mem is free again
               clr.w FreeFlagFa        ;Fast-Mem is free again
               rts
\Error:       move.l #-1,d0
               rts


DeepCopyML:
               bsr SwitchD
\DC5:          bsr TestProtect
               tst.l d0
               bpl \DC3
               bsr protect_Destination
               tst.l d0
               bmi \Error              ;Escape activated
               bra \DC5
\DC3:          bsr LengthTest
               tst.l d0
               bmi \Error
\DC1:
               bsr TextoutL
               bsr TrackLS             ;load Track from Source
               cmp.w #NoDisk,ErrorFlag
               beq \Error
               bsr SwitchD
               move.w StartTrack,d0
               bsr HeadPos
               bsr TextoutS
               bsr TrackWriter
               cmp.w #NoDisk,ErrorFlag
               beq \Error
               cmp.w #DiskProtect,ErrorFlag
               bne \DC2
               bsr protect_destination
               bra \Error
\DC2:          add.w #1,StartTrack
               move.w StartTrack,d0
               cmp.w EndTrack,d0
               bls \DC1
\Error:       rts


;load Track from Source or Destination.
;>= StartTrack = Track which will be loaded

TrackLS:       bsr SwitchS
               move.l TrackBuffer1,a5
               move.w StartTrack,d0
               bsr HeadPos
               bsr TrackLoader   
               rts

;Check length of Source- and Dest.-Diskette
;=>CheckLength = Length of Source-Disk
;=>LenghtDest   = Length of Dest.-Disk
LengthTest:
               bsr SwitchD
               move.w StartTrack,d0
               bsr HeadPos
               move.l TrackBuffer2,a5
               bsr erase
               move.w #Bytesread-$15,d0
               bsr Writer
               tst.l d0
               bmi \TD1                ;Disk write protected
               bsr Counter
               tst.l d0
               bmi \TD1                ;No Disk in Drive
               move.w CheckLength,LenghtDest
\TD1:          rts

;load Track after setting Motor Bits 
;>= A5 = Pointer to the Read buffer
;=> WriteAddrs = Pointer to Data for writing 
;=> SLength = Number of Bytes to be written

TrackLoader:
               move.w #CopyAttempt1,CopyTry1
Attempt1:
               move.w #CopyAttempt2,CopyTry2 
;Attempts, on NoSync
Attempt2:

;measure length of Track (Index <=> Index)
;rad data without DMA in Buffer starting at A5

               move.w #NoError,ErrorFlag
               bsr Counter         ;=> CheckLength = Length of Track
               tst.l d0            ;Disk in Drive?
               bmi \TrackLoaderEnd

;measure distance from Index to Sync 
;if no Sync, then D0 = -1
;=> Syncwidth = distance to Sync

               bsr Syncdistance
               tst.l d0
               bpl \OK2
               sub.w #1,CopyTry2
               bne Attempt2

;Program part when no Sync is found 

\TL7:          move.l TrackBuffer2,a5
               bsr CopyOSync
               bra \TL11

\OK2:
               move.w CheckLength,d0
               add.w #$100,d0
               move.w #WithSync,d1
               bsr loader
               move.w SyncWord,(a5)      ;store first Sync 

;determine number of Bytes to Track (Sync to Sync)
;=> D0 = -1, if number deviates too much from CheckLength 
;=> TrackBytes = Length of Track

               bsr SrchTEnd
               tst.l d0
               bpl \TL3
               bsr SrchTEnd2
               tst.l d0
               bpl \TL3
               sub.w #1,CopyTry1
               bne Attempt1

               move.w CheckLength,TrackBytes
               sub.w #$10,TrackBytes     ;if no End found 
                                         ;shorten Track 

;search for Gap if Sync was found 
;>= A5 Pointer to beginning of Track 
;=> Size1 = Size of the largest Block
;=> Size2 = Size of the second largest Block

;=> SizePos = Position of the largest Block
;=> SyncNum = Number of Syncs found 

\TL3:
               clr.l d0
               move.w TrackBytes,d0
               add.l a5,d0
               move.l d0,EndPos

               bsr Blockidentify
               cmp.w #SortBlockNum,SyncNum
               bls \TL2                ;Number of Sync Ok

;Too many Blocks for intermediate memory 

               move.l SizePos,BegPos   ;Gap in largest Block
               bra \TL1                ;Too many Blocks to sort
\TL2:
               bsr TrackAmiga          ;Test if Amiga-Track
               tst.l d0
               bpl \TL4                ;branch if Amiga-Track
               cmp.b #ON,sy            ;Sync correction
               bne \TL5                ;no
\TL4:          bsr Synccorrector
\TL5:          bsr OrderBlocks
               bsr SearchGap
\TL1:          move.l TrackBuffer2,a4  ;Destination for copying
               bsr Entirecopy
\TL11:         clr.l d0                ;erase Error-Flag
\TrackLoaderEnd:
               rts

;load Track which has no Sync 
;>= A5 = Track-Buffer
;=> GapLength = Length of Gap
;=> Syncwidth = 0  (no Sync)
;=> TrackBytes = Number of Bytes on the Track

CopyOSync:
               movem.l d2-d3,-(a7)
               move.w CheckLength,d0
               cmp.w #Bytesread-50,d0    ;Source-Track too long
               bcc \COS7
               add.w #36,d0
               bra \COS6
\COS7:         move.w #Bytesread-50,CheckLength
               move.w #Bytesread-16,d0
\COS6:         move.w #WithoutSync,d1
               bsr loader
               tst.l d0
               bmi \COS1
               move.w CheckLength,d1
               sub.w #50,d1

               move.l a5,a0              ;Track-Buffer
               move.b (a0)+,d2           ;get first Byte 
\COS2:         move.b (a0)+,d3
               cmp.b d2,d3               ;compare Bytes 
               bne \COS4                 ;not equal 
               sub.w #1,d1               ;increase number 
               bne \COS2
               bra \COSOK                ;Track the same everywhere 

\COS4:         add.l #2,a0               ;jump over Gap 
               move.b (a0)+,d2
\COS3:
               move.b (a0)+,d3
               cmp.b d2,d3               ;compare Bytes 
               bne \COSNO                ;not always the same 
               sub.w #1,d1               ;increment Counter 
               bne \COS3
               move.l a5,a0

\COSOK:        move.w LenghtDest,d0
               add.w #$10,d0
\COS5:         move.b d2,(a0)+
               dbf d0,\COS5
\COSNO:        move.w LenghtDest,d0
               add.w #$4,d0
               move.w d0,TrackBytes
               move.w d0,SLength         ;number of write bytes
               move.l a5,WriteAddrs      ;beginning of Data 
               move.w #NoSync,ErrorFlag
               clr.l d0
               movem.l (a7)+,d2-d3
               rts
\COS1:         move.l #-1,d0
               rts

TrackWriter:
               move.l WriteAddrs,a5
               move.w SLength,d0
               bsr Writer
               rts
erase:
               move.l TrackBuffer2,A0
               move.w #(Bytesread-$10)/4,d0
\ER2:          move.l #$aaaaaaaa,(a0)+
               dbf d0,\ER2
               rts

;determine copy area (Start- and End-Cylinder)
;>= StartTrack = Track where start is made (Track!!)
;>= EndTrack   = Track which is copied last (Track!!)

Start_End:     clr.l d0
               move.b fc,d0              ;first Cylinder
               lsl.b #1,d0               ;Cylinder => Track
               move.w d0,StartTrack
               move.w d0,TNumBufferA
               move.b lc,d0              ;last Cylinder
               lsl.b #1,d0               ;Cylinder => Track
               add.w #1,d0               ;last Track = bottom side
               move.w d0,EndTrack
               rts

;test if Disk is in the Drive
;=> D0 = -1, if no Disk in the Drive

DiskInFloppy:
               clr.l d0
               move.b $bfe001,d0
               btst #2,d0
               bne \DIF
               move.l #-1,d0
               move.w #NoDisk,ErrorFlag
\DIF:          rts

;load Track 
;A5 = Pointer to Data-Buffer

Loader:        MOVEM.L d2-d3,-(A7)
               move.w d0,d3              ;read Byte num
               lsr.w #1,d3
               bsr DiskInFloppy
               tst.l d0
               bmi \L1
               MOVE.W #$8010,$DFF096     ;enable Disk-DMA 
               move.w #$7f00,$DFF09E     ;erase Disk-Bits 
               MOVE.L A5,A1              ;Pointer to Data-Buffer
               MOVE.L A1,$DFF020         ;pass Data-Buffer 
               cmp.w #WithSync,d1
               bne \L3
               MOVE.W SyncWord,$DFF07E   ;pass SYNC-Word 
               move.w #$8500,$DFF09E
               lea 2(a5),a1
               move.l a1,$DFF020         ;pass new Address 
               bra \L4

\L3:           MOVE.W #$8100,$DFF09E     ;To MFM-Format
\L4:           MOVE.W #$4000,$DFF024     ;prepare transmission
               bsr Index                 ;wait to Index 
               tst.l d0
               bmi \L1
               or.w #$8000,d3
               MOVE.W d3,$DFF024
               MOVE.W d3,$DFF024         ;read Data 
               clr.l d0                  ;report Ok 
               MOVE.L #$18000,D1         ;set time counter 
               move.w #$0002,$dff09c     ;erase Blockdone-Int. 
\L2:           MOVE.W $DFF01E,D2
               BTST #1,D2
               BNE.S \L1             ;wait for Disk-Block-Ready
               SUBQ.L #1,D1          ;decrement Counter
               BNE.S \L2             ;branch when not done 
               move.l #-1,d0
\L1:           MOVE.W #$4000,$DFF024
\L5:           MOVEM.L (A7)+,D2-d3
               RTS

;wait for Index hole 

Index:
               move.l d1,-(a7)
               clr.l d0
               move.l #$30000,d1
               MOVE.B $BFDD00,D0
Index1:        MOVE.B $BFDD00,D0         ;wait for Index hole 
               BTST #4,D0
               Bne.s Index2
               sub.l #1,d1
               bne Index1
               move.l #-1,d0
Index2:
               move.l (a7)+,d1
               rts


;determine Motorbits, set Heads to zero
HeadMov:
               movem.l d2-d4,-(a7)
               clr.w d3
               move.b DD,d2             ;Dest.-Drives
               or.b SD,d2               ;Source-Drives
\KA1:          clr.l d0
               btst d3,d2               ;Drive now in use ?
               beq \KA2                 ;not in use 
               bset d3,d0               ;Bit for Drive
               lsl.b #3,d0
               eor.b #$fb,d0
               move.b d0,MotorBits
               bsr MotorOn
               clr.l d0
               bsr HeadPos
\KA2:
               addq.w #1,d3
               cmp.w #4,d3
               bne \KA1

               bsr MotBits
               move.b MotorBitsD,MotorBits
               move.b #-1,Flag
               clr.w TrackNumS
               clr.w TrackNumD
               bsr SwitchS
               movem.l (a7)+,d2-d4
               rts
TestDrive:
               move.l a0,-(a7)
               lea $bfd000,a0
               bclr #1,MotorBits
               bsr Stepper
               bset #1,MotorBits
               bsr Stepper
               move.l (a7)+,a0
               rts

;=> D0 = -1 => Disk protect
TestProtect:   bsr TestDrive
               clr.w ErrorFlag
               move.b $bfe001,d0
               btst #3,d0
               bne \TP2
               move.w #DiskProtect,ErrorFlag
               move.l #-1,d0
               bra \TP1
\TP2:          clr.l d0
\TP1:          rts

;place Head in position indicated by D0 
  
HeadPos:       MOVEM.L D0-D3,-(A7)
               lea $bfd000,a0
               tst.w d0
               beq HeadNull
               move.w TrackNum,d2      ;current Track-Number
               CMP.W d2,D0
               BEQ.S Headend           ;End when right Track
               move.w d0,d3            ;Track-Number to D3
               move.b MotorBits,d1
               bset #2,d1              ;lower Head 
               btst #0,d3
               beq Upper               ;select lower Head 
               bclr #2,d1
Upper:         move.b d1,MotorBits     ;upper Head
               move.b d1,$100(a0)
               move.w d3,TrackNum
               lsr.w #1,d2
               lsr.w #1,d3             ;calculate steps 
               sub.w d3,d2
               bcs.s In
               bhi.s Out
               bra Headend
In:            bclr #1,d1
               move.b d1,MotorBits
               neg.w d2
               bra.s rechok
Out:           bset #1,d1
               move.b d1,MotorBits
               bra.s rechok
Heads:         bsr Stepper
rechok:        dbf d2,Heads
Headend:       movem.l (a7)+,d0-d3
               rts

HeadNull:
               move.b Motorbits,d1
               bset #2,d1
               bset #1,d1
               move.b d1,Motorbits
               clr.w TrackNum
HeadNull1:     move.b $bfe001,d0
               btst #4,d0
               beq.s \He1
               bsr Stepper
               bra HeadNull1
\He1:          bclr #1,MotorBits
               bsr Stepper
               bset #1,MotorBits
               bsr Stepper
               bra Headend

Stepper:
               move.b MotorBits,d0
               lea $100(a0),a1
               move.b d0,d1
               bclr #0,d0
               move.b d0,(a1)
               nop
               nop
               move.b d1,(a1)
               jsr Timer
               move.b MotorBits,(a1)
               rts

;Wait loop

Timer:         MOVE.L D7,-(A7)
               MOVE.W #2500,D7
\L1:           DBRA D7,\L1
               MOVE.L (A7)+,D7
               RTS
Timer2:        MOVE.L D7,-(A7)
               MOVE.L #$6000,D7
\L1:           sub.l #1,D7
               bne \L1
               MOVE.L (A7)+,D7
               RTS

;Motor routine:   D0=0 => Motor off 

MotorOff:      clr.l d0
               bra Motor
MotorOn:       move.b #$01,d0

Motor:         movem.l d1/d2,-(a7)
               lea $bfd000,a0
               tst d0
               seq d1
               andi.b #$80,d1
               move.b MotorBits,d2
               andi.b #$80,d2
               cmp.b d1,d2
               beq.s Mook
               bclr #7,MotorBits
               or.b d1,MotorBits
               move.b #$ff,d1
               eor.b d2,d1
               move.b d1,$100(a0)
               move.b MotorBits,$100(a0)
               btst #7,MotorBits
               bne Mook
               jsr Timer2
Mook:          movem.l (a7)+,d1/d2
               rts

Disable:       move.w #$4000,$dff09a
               move.l a6,-(a7)
               move.l $4,a6
               add.b #1,IDNestCnt(a6)
               move.l (a7)+,a6
               rts
Enable:        move.l a6,-(a7)
               move.l $4,a6
               sub.b #1,IDNestCnt(a6)
               bge L005
               move.w #$c000,$dff09a
L005:          move.l (a7)+,a6
               rts

;Waits for Byte during read and stores Byte (a0)+

               rts

;>= a0 = Address of data to be found 
;>= A1 = Address where search starts 
;>= Searchln = Number of words for error
;>= NumWords = Number of Words which is compared 
;=> D1 = Number of Bytes to fund
;=> Position = where found 
;=> D0 = -1 = not found 
;=> A0 = Position where found 

Bitsrch:
               movem.l d2-d6/a2-a4,-(a7)
               move.l a0,a2
               move.l a1,a3
               clr.w d5
               move.w Searchln,d4        ;Search num
srch2:         move.w #00,d3             ;number of shift Bits 
srch1:         move.l (a2),d1
               move.l (a3),d2
               bsr comp
               tst.w d0
               beq srchok
               move.l a0,a2
               tst.w d5
               beq srch4
               clr.w d5
               move.w d6,d3
               move.l a4,a3
  
srch4:         add.w #1,d3
               cmp.w #$10,d3
               bne srch1
srch3:         add.l #2,a3
               clr.w d5                  ;compare the right ones 
               dbf d4,srch2              ;Counter for attempts 
               move.l #-1,d0             ;not found 
               bra srchend
srchok:
               tst.w d5
               bne srchok2
               move.l a3,a4
               move.w d3,d6

srchok2:       add.w #1,d5
               cmp.w NumWords,d5
               beq srchend1
               add.l #2,a2
               add.l #2,a3
               bra srch1
srchend1:      move.l #0,d0
               sub.w #1,d5
               lsl.w #1,d5
               suba.l d5,a3
               move.l a3,a0
               move.l a3,Position
               move.l a3,a0           ;Position
               move.w d3,BitShifts    ;Bit shifting 
               sub.l a1,a3
               move.l a3,d1           ;Number of Bytes until found 
srchend:       movem.l (a7)+,d2-d6/a2-a4
               rts
comp:          movem.l d1-d2,-(a7)
               lsl.l d3,d2
               swap d1
               swap d2
               eor.w d1,d2
               move.w d2,d0
               movem.l (a7)+,d1-d2
               rts



MotBits:
               move.b SD,d0              ;Source-Disk
               lsl.b #3,d0
               eor.b #$fb,d0
               move.b d0,MotorBitsS
               move.b DD,d0              ;Dest.-Disk
               lsl.b #3,d0
               eor.b #$fb,d0
               move.b d0,MotorBitsD
               rts

;switch on next Dest.-Drive 
;!!! Caution !!! old Motorbits are reset 
;>= D1 = which Drive ( < 4)
;=> D0 = -1, if no additional Drive available 
;=> D0 = Null if OK

SwitchND:
               move.l d2,-(a7)
               clr.l d0
               move.b DD,d2
               btst d1,d2                ;Drive connected ?
               bne \SND1                 ;yes, connected 
               move.l #-1,d0
               bra \SND2
\SND1:         bset d1,d0                ;Bit for Drive
               lsl.b #3,d0
               eor.b #$7b,d0
               move.w StartTrack,d1
               bset #2,d0
               btst #0,d1
               beq \SND3                 ;lower Head select 
               bclr #2,d0
\SND3:         move.b d0,MotorBits       ;upper Head
               move.b d0,$bfd100
               clr.l d0
\SND2:         move.l (a7)+,d2
               rts

SwitchS:
               tst.b Flag
               bpl \S1
               move.b MotorBits,MotorbitsD
               move.w TrackNum,TrackNumD
               move.b MotorBitsS,MotorBits
               move.w TrackNumS,TrackNum
               move.b #$7f,$bfd100
               move.b MotorBits,d0
               bclr #7,d0
               move.b d0,$bfd100
               move.b d0,MotorBits
               clr.b Flag
\S1:           rts
SwitchD:
               tst.b Flag
               bmi \S1
               move.b MotorBits,MotorbitsS
               move.w TrackNum,TrackNumS
               move.b MotorBitsD,MotorBits
               move.w TrackNumD,TrackNum
               move.b #$7f,$bfd100
               move.b MotorBits,d0
               bclr #7,d0
               move.b d0,$bfd100
               move.b d0,MotorBits
               move.b #-1,Flag
\S1:           rts


;store Track 
;>= D0 = number of Bytes to write 
;>= A5 = Track-Buffer
;>= D1 = Indication if wait for Index (IndexOk/NoIndex)

Writer:     MOVEM.L D2-D3,-(A7)
               move.w d1,d2
               move.w d0,d3              ;Number to D3
               clr.w ErrorFlag
               bsr DiskInFloppy
               tst.l d0
               bmi \Protect
               move.b $bfe001,d0
               btst #3,d0
               bne \SR5
               move.w #DiskProtect,ErrorFlag
               bra \Protect
\SR5:          lsr.w #1,d3               ;from Byte make Word
               jsr MotorOn
               MOVE.W #2,$DFF09C         ;erase Disk-Block-Int. 
               MOVE.L A5,$DFF020         ;pass Data-Buffer 
               MOVE.W #$8210,$DFF096     ;enable Disk-DMA 
               move.w #$7f00,$dff09e
               MOVE.W #$8100,$DFF09E     ;MFM-Format
               cmp.w #80,StartTrack
               bcs \SR1
               move.w #$a000,$dff09e     ;Pre-compensation
\SR1:          MOVE.W #$4000,$DFF024     ;prepare transmission 
               cmp.w #NoIndex,d2
               beq \SR2
               bsr Index
               tst.l d0
               bmi \Protect
\SR2:          or.w #$c000,d3            ;switch to write 
               MOVE.W d3,$DFF024
               MOVE.W d3,$DFF024         ;write Data 
               clr.l d0                  ;pass OK message 
               MOVE.L #$20000,D1         ;set time counter 
\SR3:          MOVE.W $DFF01E,D2
               BTST #1,D2
               BNE.S \SR4            ;wait for Disk-Block-Ready 
               SUBQ.L #1,D1          ;decrement Counter 
               BNE.S \SR3            ;branch when not done 
\Protect:      move.l #-1,d0
\SR4:          move.w #$4000,$dff024
               MOVEM.L (A7)+,D2-D3
               RTS
;Searches for Track-End when Sync found 
;>= A5 = Pointer to Track-Buffer (Sync found)
;=> TrackBytes = Number of Bytes on the Track (seek for Sync)
;=> D0 = -1, too much deviation from CheckLength

SrchTEnd:
               move.l a5,a0
               clr.l d0
               move.w CheckLength,d0
               sub.w #$4,d0
               adda.l d0,a0
               move.w #$10,d0
               bsr SrchSync
               tst.l d0
               bmi \STE2
               suba.l a5,a0
               sub.w #2,a0
               move.w a0,TrackBytes
               rts
\STE2:         move.l #-1,d0
               move.w #LengthUnequal,ErrorFlag
               rts

SrchTEnd2:
               move.l a5,a0
               adda.l #$04,a0
               move.l a0,a1
               clr.l d0
               move.w CheckLength,d0
               sub.w #$40,d0
               adda.l d0,a1
               move.w #$40,Searchln
               move.w #$60,NumWords
               bsr Bitsrch
               tst.l d0
               bmi \STE2
               suba.l a5,a0
               suba.l #6,a0              ;Position before Sync
               move.w a0,TrackBytes
               rts
\STE2:         move.l #-1,d0
               move.w #LengthUnequal2,ErrorFlag
               rts

;search for Blocks and store
;>= A5 = Pointer to Track beginning 
;=> Size1 = Size of the largest Block
;=> Size2 = Size of the second largest Block
;=> SizePos = Position of the largest Block
;=> SyncNum = Number of Syncs found
;=> Blocks = Buffer in which the Block sizes are stored
Blockidentify: movem.l d2-d4/a3,-(a7)
               move.w TrackBytes,d2      ;Bytes on Track
               move.l a5,a3              ;Beginning of Track
               clr.w Size1
               clr.w Size2
               clr.w SyncNum
               clr.w d3

\S2:           move.w d2,d0
               move.l a3,a0              ;where to start search 
               bsr SrchSyncF
               tst.l d0
               bmi \S5                   ;End
               tst.w d1
               beq \S6
               move.w d3,d4
               add.w d1,d3               ;Number + Sync
               bsr Blockentry
               bsr Size
               clr.w d3                  ;Sync gap = 0
\S6:
               add.w #2,d3               ;Sync gap +2
               add.w #2,d1
               andi.l #$ffff,d1
               adda.l d1,a3
               sub.w d1,d2
               bcc \S2
               bra \S7
\S5:           move.w d2,d1
               add.w #2,d1               ;Number +2
               move.w d3,d4              ;Sync message 
               add.w d1,d3               ;Number + Syn
               bsr Blockentry
               bsr Size
\S7:           movem.l (a7)+,D2-d4/A3
               rts

;Enter size of Blocks
;>= D1 = Block size 

Size:
               cmp.w Size1,d3
               bcs \S3
               move.w Size1,Size2
               move.w d3,Size1
               move.l a0,a1
               move.l a1,SizePos
               bra \S4
\S3:           cmp.w Size2,d3
               bcs \S4
               move.w d1,Size2
\S4:           rts

Blockentry:
               move.w SyncNum,d0
               cmp.w #$40,d0             ;Too many Blocks ?
               bcc \S1                   ;yes, do not store 
               lsl.w #2,d0
               lea Blocks,a1
               lsr.w #1,d4
               move.w d4,(a1,d0)
               add.w #2,d0
               move.w d3,(a1,d0)         ;store Block 
\S1:           add.w #1,SyncNum
               rts

;seek Sync-Mark (fast)
;>= A0 = Search address
;>= D0 = Byte number for errors permitted
;=> A0 = Sync address
;=> D0 = -1, no Sync found 
;=> D1 = found after xx Bytes 
SrchSyncF:
               lsr.w #1,d0               ;from Byte make Word
               move.l a0,a1
\SSF2:         cmp.w #$4489,(a0)+
               beq \SSF1
               dbf d0,\SSF2
               move.l #-1,d0
               bra \SSF3
\SSF1:         suba.l #2,a0
               move.l a0,d0
               sub.l a1,a0
               move.w a0,d1
               move.l d0,a0
               clr.l d0
\SSF3:         rts
;search for Sync-Mark 
;>= A0 = Search address
;>= D0 = Byte number for errors permitted 
;=> A0 = Sync address
;=> D0 = -1, no Sync found 
;=> D1 = found after  xx Bytes 
;=> BitShifts = shifted by xx Bits 



SrchSync:
               movem.l d2-d4/a2,-(a7)
               move.l a0,a2
               lsr.w #2,d0         ;Byte out, with longword value
               lea SyncBase,a1
\SS3:          clr.l d1
               move.l #$ffff0000,d3
               move.l (a0)+,d2
\SS2:          move.l d2,d4
               and.l d3,d4
               cmp.l (a1,d1),d4
               beq \SS1
               add.w #4,d1
               lsr.l #1,d3
               cmp.w #$40,d1
               bls \SS2
               dbf d0,\SS3
               move.l #-1,d0
               bra \SS4
\SS1:          clr.l d0
               lsr.w #2,d1
               move.w d1,BitShifts
               cmp.w #$8,d1
               bcc \SS5
               suba.l #2,a0
\SS5:          suba.l #2,a0
               move.l a0,d1
               suba.l a2,a0
               exg.l a0,d1
\SS4:          movem.l (a7)+,d2-d4/a2
               rts

;Distance Index <=> Sync
;=> Syncwidth = Distance Index <=> Sync
;=> D0 = -1, no Sync found 

Syncdistance:
               move.l a5,a0
               move.w CheckLength,d0
               bsr SrchSync
               tst.l d0
               bpl \SE1
               move.w #NoSync,ErrorFlag
               bra \SE2
\SE1:
               move.w d1,Syncwidth
\SE2:          rts

;A5 = TrackBuffer

;Counter of Data on Disk without Sync and without DMA
;>= A5 = Pointer to Verify-Buffer for reading Data without Sync
;=> CheckLength = Length of a Track (From Index to Index)

Counter:
               bsr DiskInFloppy
               tst.l d0
               bmi \Z5
               movem.l d2-d4/a2-a3,-(a7)
               move.w #$0600,$dff09e     ;switch Sync off 
               move.w #$8000,$dff024
               lea $dff01b,a0
               lea $dff01a,a1
               lea $bfdd00,a2
               move.l #15,d2
               move.l #4,d3
               move.w #1,d4
               clr.w d0
               move.b (a2),d1            ;erase Byte-Ready-Flag 
\Z4:           move.b (a2),d1
               btst #4,d1
               beq.s \Z4
               move.w (a1),d1            ;erase Byte-Ready-Flag 
               move.b (a2),d1            ;erase Indexbit 
               move.l a5,a3
\Z1:
               btst d2,(a1)
               beq.s \Z1
               btst d3,(a2)
               bne.s \Z2
               add.w d4,d0
               move.b (a0),(a3)+
               bra \Z1
\Z2:
               andi.w #$fffe,d0
               move.w d0,CheckLength
               cmp.w #Bytesread,d0       ;Track too long 
               bcs \Z6
               move.w #Bytesread-16,CheckLength
\Z6:           bclr #31,d0               ;erase Errorbit 
               movem.l (a7)+,d2-d4/a2-a3
\Z5:           move.w #$4000,$dff024
               rts

;Sort Block sizes 

OrderBlocks:
               move.l d2,-(a7)
               cmp.w #SortBlockNum,SyncNum
               bhi \OBEND                ;too many Blocks 
               tst.w SyncNum
               beq \OBEND                ;no Blocks 
               clr.w NumSortBlock
               lea Blocks,a0
               move.w SyncNum,d0
\OB5:          move.l (a0)+,d1
               sub.w #1,d0
               lea SortBlocks,a1         ;Number of Blocks -1
               move.w NumSortBlock,d2
               tst.w d2
               beq \OB2                  ;first Block
\OB4:          cmp.w (a1)+,d1
               bne \OB3                  ;found 
               add.w #1,(a1)
               bra \OB6
\OB3:          adda.w #2,a1
               sub.w #1,d2
               bne \OB4                  ;continue search 
\OB2:          move.w d1,(a1)+
               move.w #1,(a1)+
               add.w #1,NumSortBlock
\OB6:          tst.w d0
               bne \OB5                  ;new search 
\OBEND:        move.l (a7)+,d2
               rts

SearchGap:
               move.l d2,-(a7)
               clr.l BegPos
               move.w NumSortBlock,d0

               cmp.b #1,dc1
               beq \SL10        ;DeepCopy 1 (Gap after large Block)

;search for single Blocks

               sub.w #1,d0               ;Block number -1
\SL3:
               bsr SingleBlock           ;search for single Block
               tst.l d0                  ;Gap found ?
               bpl \SL7                  ;branch when not found 
\SL10:         move.l SizePos,a0         ;Gap with largest Block
\SL7:
               move.l A0,BegPos
               cmp.l EndPos,a0
               bcs \SL8
               move.l a5,a0
               move.l a0,BegPos
\SL8:
               move.l SizePos,d0
               cmp.l EndPos,d0
               bcs \SL9
               move.l a5,SizePos
\SL9:          move.l (a7)+,d2
               rts



;Search for single Block 
;=> D0 = Block number
;=> D0 = Block number of next Block
;=> D0 = -1, when none found 
;=> D1 = Size of Block
;=> a0 = Address of the Blocks

SingleBlock:
               movem.l d2-d4,-(a7)
               and.l #$ffff,d0           ;erase error message
               tst.w d0
               bmi \EB3
               lea SortBlocks,a0
\EB2:          move.w d0,d1
               lsl.w #2,d1
               move.l (a0,d1),d2
               cmp.w #1,d2
               beq \EB1                  ;Block found 
               sub.w #1,d0
               tst.w d0
               bpl \EB2
\EB3:          move.l #-1,d0
               bra \EBEND                ;Error 
\EB1:          move.w (a0,d1),d2         ;Block length 
               clr.w d3                  ;erase Blockadr. 
               lea Blocks,a0
\EB4:          move.l (a0)+,d1
               add.w d1,d3               ;determine Address 
               cmp.w d1,d2
               bne \EB4                  ;continue if not done
               sub.l a0,a0               ;clear A0
\EB5:          move.w d3,a0              ;Offset
               add.l a5,a0               ;Address
               move.w d2,d1              ;Block size
               sub.w #1,d0               ;Number of next Block
\EBEND:        movem.l (a7)+,d2-d4
               rts

;Test if Track on Amiga-Format
;=> D0 = Null, if Track Amiga-Format
;=> D0 = -1, if not Amiga-Format
TrackAmiga:
               move.l d2,-(a7)
               lea Blocks,a0          ;Pointer to Block storage 
               cmp.w #$0b,SyncNum     ;SyncNumahl for Amiga-Format
               bne \PL1               ;No not Amiga-Format
               clr.w d1
               clr.l d2
               move.w #$0a,d0
\PL3:          move.w d0,d2
               lsl.w #2,d2
               cmp.w #$0440,2(a0,d2)    ;Block length for Amiga
               bne \PL2
               add.w #1,d1
\PL2:          dbf d0,\PL3
               cmp.w #$9,d1             ;at least 9 Amiga-Blocks 
               bcs \PL1
               clr.l d0                 ;OK, Amiga-Format
               move.b #ON,AmigaTrack
\PL4:          move.l (a7)+,d2
               rts
\PL1:          move.l #-1,d0            ;not Amiga-Format
               move.b #OFF,AmigaTrack
               bra \PL4
;The program assumes that all Syncs are equal in length
;all Syncs are fitted to the first 
;>= A5 = Pointer to Track-Buffer

Synccorrector:
               movem.l d2-d4,-(a7)
               cmp.w #1,SyncNum
               beq \SK1                 ;only one Sync
               lea Blocks,a0
               clr.w d0
               clr.l d3
               move.l a5,a1
               move.l (a0)+,d2
               move.w d2,d3             ;Block length
               swap d2                  ;Sync value
\SK3:          adda.l d3,a1             ;Pointer to Block
               add.w #1,d0
               cmp.w SyncNum,d0
               bcc \SK1
               move.l (a0)+,d1
               move.w d1,d3             ;Block length
               swap d1                  ;SyncNum from Block
               cmp.w d2,d1
               bcc \SK3                 ;do not correct
               sub.w d2,d1
               not.w d1
               move.w d1,d4             ;Number of new Syncs
               move.l a1,-(a7)
\SK2:
               cmp.l SizePos,a1         ;must Pos be changed 
               bne \SK8
               sub.l #2,SizePos         ;change SizePos 
\SK8:          move.w #$4489,-(a1)

               dbf d4,\SK2
               move.l (a7)+,a1
               add.w #1,d1
               add.w d1,-4(a0)
               lsl.w #1,d1
               sub.w d1,-6(a0)
               add.w d1,-2(a0)
               bra \SK3
\SK1:          cmp.w #LengthUnequal,ErrorFlag
               beq \SK7                 ;no end correction required
               move.w d2,d0             ;Sync value
               move.l EndPos,a1
               add.l #2,a1              ;set Pointer to Sync
               bra \SK4
\SK6:          cmp.w #$4489,(a1)+       ;test transition to beginning 
               bne \SK5
\SK4:          dbf d0,\SK6
\SK7:          movem.l (a7)+,d2-d4
               rts
\SK5:          sub.w d0,d2
               lsl.w #1,d2
               sub.l #2,EndPos
               sub.w #2,TrackBytes
               sub.w #2,-2(a0)          ;Last Block is shorter
               bra \SK7

;after the Gap has been determined, the Data are copied
;and written 
;>= A5 = TrackBuffer (Source)
;>= A4 = TrackBuffer (Destination)

Entirecopy:
               move.l a2,-(a7)
               move.l a4,a1
               move.l BegPos,a0
               sub.l a5,a0              ;Offset of the beginning 
               clr.l d0
               move.w Syncwidth,d0
               sub.w #$0044,d0          ;distance correction 
               bcc \UK6                 ;distance too small ?
               clr.w d0                 ;yes, distance = 0
\UK6:
               add.l d0,a0              ;distance from Index
               move.w a0,Offset         ;number of Bytes before Sync
               suba.l a0,a1             ;beginning of writing 
               move.l a1,WriteAddrs
               move.w TrackBytes,d0
               lsr.w #1,d0              ;Byte to Word
               move.w LenghtDest,d1
               move.l BegPos,a0         ;Source-Address 
               move.l a4,a1             ;Destination-Address
               cmp.b #ON,AmigaTrack
               bne \UK9
               add.l #4,a1
\UK9:          move.l #$aaaaaaaa,-4(a1)
\UK4:          move.w (a0),(a1)+
               sub.w #1,d1
               cmp.l EndPos,a0
               bcs \UK3
               move.l a5,a0
               bra \UK5
\UK3:          adda.l #2,a0
\UK5:          dbf d0,\UK4
               move.l (a7)+,a2
               and.w #$f000,d1
               bne \UK8              ;Source longer than Destination 
\UK7:          move.w #$aaaa,(a1)+   ;if Dest. is longer than Source
               dbf d1,\UK7
\UK8:          move.w LenghtDest,d0
               sub.w #$0006,d0
               add.w Offset,d0
               move.w d0,SLength
               rts
;read Track and decode 
;>= A4 = Pointer to Buffer for decoded Data
;>= A5 = Pointer to Buffer for coded Data

FastReads:
               MOVEM.L D2-D4/a3/a6,-(A7)
               lea decode,a3             ;Jump point for decode
               move.w #$080,DecodeCnt    ;number of 
                                         ;Longwords to decode 
               lea $40(a5),a0
               move.l a0,DecodeAdr       ;Data area of first Block
               adda.l #$400,a0
               move.l a0,FTestAdr        ;Address of the next Block
               move.w #OFF,VerifyFlag
               bra Fread

FastVerify:    movem.l d2-d4/a3/a6,-(a7)
               lea FVerify,a3            ;Jump point for Verify
               move.l a5,DecodeAdr
               lea $440(a5),a0
               move.l a0,FTestAdr
               move.w #ON,VerifyFlag

Fread:
               clr.w ErrorFlag
               bsr DiskInFloppy
               tst.l d0
               bmi \FastError
               MOVEA.L A5,A6             ;Track-Buffer
               move.l #$aaaaaaaa,(a6)+
               move.w #$4489,(a6)+       ;enter first Sync 
               bsr search
               tst.l d0
               bmi \FreadEnd

               bsr FErase                ;prepare Track-Buffer 
               clr.l d2
               move.w BytesBefGap,d2     ;display Byte before Gap
               tst.l d2
               beq \FL1                  ;No Byte before Gap
               clr.w BlockAdr            ;Offset in Block
               bsr Readbyte              ;read Byte 
               clr.l d0
               move.w BytesBefGap,d0
               move.l a5,a6
               adda.l d0,a6              ;Pointer to next Buffer
               move.l #$aaaaaaaa,(a6)+
               move.w #$4489,(a6)+       ;enter first Sync 
\FL1:          move.w BytesAftGAp,d2
               tst.l d2
               beq \FL2
               clr.w BlockAdr
               bsr Readbyte
\FL2:          cmp.w #ON,VerifyFlag
               beq \FL3
               bsr lastblock     ;no last Block during Verify
\FL3:          BTST #2,$BFE001
               BEQ.S \FastError          ;Error, if no Disk
               MOVEQ #0,d0               ;OK-Message 
               move.l #$aaaaaaaa,$2ec0(a5)
                                         ;create Gap after Data
               bra \FreadEnd
\FastError:   move.l #-1,d0
\FreadEnd:    MOVEM.L (A7)+,D2-D4/a3/A6
               RTS

;prepare Track-Buffer (erase Block starts)
;>= A5 = Pointer to Track-Buffer

FErase:        move.l a5,a0
               move.w #10,d1
               clr.l d0
\L1:           move.l d0,$440(a0)
               adda.l #$440,a0
               dbf d1,\L1
               lea BlockMessage,a0
               move.w #10,d1
\L2:           clr.w (a0)+
               dbf d1,\L2
               rts

;read number of Bytes selected 
;>= A6 = Pointer to Destination
;>= D2 = Number of Bytes to be read 

Readbyte:
               jsr install
               MOVE.W D2,D0
               LSR.W #1,D0
               ORI.W #$8000,D0
               add.w #1,d0
               MOVE.W D0,36(A1)
               MOVE.W D0,36(A1)
               jsr (a3)
               LEA $DFF000,A1
               MOVE.W #$4000,$24(A1)
               rts

;preparation for reading 
;>= A6 Pointer to Track-Buffer

install:       LEA $DFF000,A1
               move.w #$4000,$24(a1)     ;reset Disk-Len 
               move.w #$8400,$9e(a1)     ;switch on Disk-Sync 
               move.w #$4489,$7e(a1)     ;SYNC-Mark 
               MOVE.L A6,$20(A1)         ;pass Buffer 
               move.w #$0002,$dff09c
               rts

;code Longword and store in Buffer 
;>= D0 = Longword
;>= A0 = Pointer to Buffer

CodeLWord:     MOVEM.L D2-D3,-(A7)
               MOVE.L D0,D3
               LSR.L #1,D0
               BSR \CH1
               MOVE.L D3,D0
               BSR \CH1
               BSR SetBorders
               MOVEM.L (A7)+,D2-D3
               RTS
\CH1:          ANDI.L #$55555555,D0
               MOVE.L D0,D2
               EORI.L #$55555555,D2
               MOVE.L D2,D1
               LSL.L #1,D2
               LSR.L #1,D1
               BSET #$1F,D1
               AND.L D2,D1
               OR.L D1,D0
               BTST #0,-1(A0)
               BEQ.S \CH2
               BCLR #$1F,D0
\CH2:          MOVE.L D0,(A0)+
               RTS
;set borders properly 

SetBorders:    MOVE.B (A0),D0
               BTST #0,-1(A0)
               BNE.S \CH4
               BTST #6,D0
               BNE.S \CH6
               BSET #7,D0
               BRA.S \CH5
\CH4:          BCLR #7,D0
\CH5:          MOVE.B D0,(A0)
\CH6:          RTS

;determine Checksum for Data area 
;>= D1 = number of Bytes (must always be divisible by 4)
;>= A0 = Pointer to Buffer
;=> D0 = Checksum

TestSum:       MOVE.L D2,-(A7)
               LSR.W #2,D1
               SUBQ.W #1,D1
               MOVEQ #0,D0
\PS1:          MOVE.L (A0)+,D2
               EOR.L D2,D0
               DBRA D1,\PS1
               ANDI.L #$55555555,D0
               MOVE.L (A7)+,D2
               RTS

;decode Block-Header 
;>= A0 is Pointer to Header
;=> D0 = Header

Header:        move.l (a0)+,D0
               move.l (a0)+,D1
               andi.l #$55555555,d0
               andi.l #$55555555,d1
               lsl.l #1,D0
               or.l D1,D0
               rts

;find first undisturbed Block 
;=> A6 = Pointer to Track-Buffer
;=> D0 = Null: Block found 
;=> BytesBefGap = Number of Bytes before the Gap
;=> BytesAftGAp = Number of Bytes after the Gap

search:
               movem.l d2-d4,-(a7)
               move.w #11,d2             ;Number of errors permitted
\SU1:          bsr install
               move.w #$8024,d0          ;read $24-Words 
               MOVE.W D0,$dff024
               MOVE.W D0,$dff024
               bsr Blockready            ;wait for Block-Ready 
               tst.l d0                  ;Error, then D0 = -1
               bmi \SUError

               lea 8(a5),a0              ;Pointer to Block-Header
               moveq #$28,d1             ;number of Long words
               bsr TestSum               ;Sum for Header
               move.l d0,d3              ;save Sum 
               lea 48(a5),a0             ;*Sum
               bsr Header                ;get Sum from Header 
               cmp.l d0,d3               ;compare Sums 
               bne \SUNeu
               lea 8(a5),a0
               jsr Header                ;decode Header 
               move.w d0,d3              ;Header to D3
               lsr.w #8,d3
               andi.w #$00ff,d3          ;isolate Sector number 
               addi.w #1,d3              ;increment Sector number 
               cmp.w #$000a,d3           ;Number bigger than 10?
               bls \SU2                  ;No, OK
               clr.w d3                  ;Number = 0
\SU2:          move.w d3,SectNum         ;store Number 
               move.w d3,FirstBlock      ;Number first Block

               move.w d0,d3              ;Header
               andi.w #$ff,d3            ;Sectors to Gap
               cmp.b #$0c,d3             ;Header OK?
               bcs.s \SUok
\SUNeu:        dbf d2,\SU1
               bra \SUError
\SUok:

               sub.w #1,d3               ;number of Blocks to Gap
               move.w d3,d2
               move.w #$000b,d4
               sub.b d2,d4               ;Number of Blocks after Gap
               mulu #$440,d3             ;Number of Bytes to Gap
               mulu #$440,d4             ;Number of Bytes after Gap
               clr.l d0
               move.w d3,BytesBefGap
               move.w d4,BytesAftGAp
               move.w #$0b,SectBL   ;Sectors before Gap after loading 
               bra \SUEnd
\SUError:      move.l #-1,d0
               move.w #ReadError,ErrorFlag
\SUEnd:        movem.l (a7)+,d2-d4
               rts

Blockready:    clr.l d0                  ;erase Error-Flag 
               move.l #$20000,d1
               move.w #$0002,$dff09c     ;erase Disk-Int. 
\B1:           MOVE.W $DFF01E,D0
               BTST #1,D0
               bne.s \B2
               sub.l #1,d1
               bne \B1
               move.l #-1,d0             ;Error occurred 
\B2:           RTS


;decode Bytes until Block has been read 

decode:
               movem.l d2-d3/a2,-(a7)
               clr.l d3
               move.w BlockAdr,d3        ;Offset in Block
               move.l FTestAdr,a0        ;Address for testing if 
                                         ;Block already loaded 
               move.l DecodeAdr,a2       ;Address where 
                                         ;decoding is done 
               move.w DecodeCnt,d2       ;Number for decoding 

\DC1:          MOVE.W $DFF01E,D0
               BTST #1,D0                ;area already read 
               bne  \DCEnd               ;Yes, End
               tst.l (a0)                ;TestAdr
               beq \DC1                  ;wait until Block has been read

               movem.l a0-a1,-(a7)       ;save Register 
               lea -$40(a2),a1           ;* Block start 
               bsr BlockCheck            ;check Block 
               movem.l (a7)+,a0-a1       ;restore Register 
               move.w SectNum,d0
               mulu #$200,d0
               move.l a4,a1              ;Base address for destination data
               add.l d0,a1               ;Address of the Block
\DC2:
               MOVE.W $DFF01E,D0
               BTST #1,D0
               bne.s \DCEnd              ;area already read 

               move.l (a2),D0
               move.l $200(a2),D1
               adda.l #4,a2
               andi.l #$55555555,d0
               andi.l #$55555555,d1
               lsl.l #1,D0
               or.l D1,D0
               move.l d0,(a1,d3)         ;enter Longword 
               addq.w #4,d3
               subq.w #1,D2              ;Decode number 
               bne \DC2
               adda.l #$240,a2           ;increment Address
               adda.l #$440,a0           ;TestAdr
               move.l #$080,D2           ;Decode number 
               clr.w d3                  ;Offset to Null
               add.w #1,SectNum          ;increment Sector number 
               cmp.w #$0b,SectNum        ;Number more than 10?
               bcs \DC3                  ;No, OK
               clr.w SectNum             ;Nummer = 0
\DC3:          bra \DC1

\DCEnd:
               move.w d3,BlockAdr
               move.l a2,DecodeAdr
               move.l a0,FTestAdr
               move.w D2,DecodeCnt

               movem.l (a7)+,d2-d3/a2
               RTS

;decode last Block 

Lastblock:
               movem.l d2-d3/a2,-(a7)

               move.w SectNum,d0
               mulu #$200,d0
               move.l a4,a1            ;Base address for destination data
               add.l d0,a1             ;Address of the Block
               clr.l d3
               move.l DecodeAdr,a2
               move.w DecodeCnt,d2
\LB1:          move.l (a2),D0
               move.l $200(a2),D1
               adda.l #4,a2
               andi.l #$55555555,d0
               andi.l #$55555555,d1
               lsl.l #1,D0
               or.l D1,D0
               move.l d0,(a1,d3)
               addq.w #$4,d3
               subq.w #1,D2               ;Decode number 
               bne \LB1
               movem.l (a7)+,d2-d3/a2
                              RTS

;test Block for Error 
;A1 = Pointer to start of Block 

BlockCheck:
               movem.l d2-d3,-(a7)
               clr.l d3
               move.w SectNum,d3
               lsl.w #1,d3               ;Sector number => Offset
               lea BlockMessage,a0
               move.w (a0,d3),d0         ;get entry 
               tst.w d0                  ;already tested ?
               bne \CBEnd2               ;yes, End

               lea 64(a1),a0
               move.w #$400,d1
               jsr TestSum               ;Sum for Data block
               move.l d0,d2              ;save Sum 
               lea 56(a1),a0             ;Pointer to Data sum 
               jsr Header                ;decode Sum 
               cmp.l d0,d2
               bne \DataFalse

               lea 8(a1),a0
               bsr Header                ;decode Header 
               move.w d0,d2              ;store lower Word 
               lsr.w #8,d2               ;Sector number to d2
               cmp.b SectNum+1,d2        ;right Sector
               bne \FalseSector
               swap d0                   ;Track-Number to D0
               cmp.b StartTrack+1,d0     ;right Track?
               bne \FalseTrack
               andi.l #$ff00,d0
               cmp.w #$ff00,d0
               bne \NotDOSTrack
               lea 8(a1),a0
               moveq #$28,d1             ;number of Longwords 
               bsr TestSum               ;Sum for Header
               move.l d0,d2              ;save Sum 
               lea 48(a1),a0             ;*Sum 
               bsr Header                ;get Sum from Header 
               cmp.l d0,d2               ;compare Sums 
               bne \HeaderFalse
               move.w #$ffff,d0
\CBEnd1:       lea BlockMessage,a0
               move.w d0,(a0,d3)
               btst #0,-1(a1)
               beq \CB1
               move.l #$2aaaaaaa,(a1)
               bra \CB2
\CB1:          move.l #$aaaaaaaa,(a1)
\CB2:          move.l #$44894489,4(a1)
               move.w #$ff00,d0          ;create new Header 
               move.b StartTrack+1,d0
               swap d0
               move.b SectNum+1,d0
               lsl.w #8,d0
               move.b SectBL+1,d0
               lea 8(a1),a0
               bsr CodeLWord             ;store Header 
               lea 8(a1),a0
               moveq #$28,d1             ;Longword number 
               bsr TestSum               ;Sum for Header
               lea 48(a1),a0             ;*Sum 
               bsr CodeLWord             ;store Checksum 
               subq.w #1,SectBL
\CBEnd2:       movem.l (a7)+,d2-d3
               rts

\FalseSector: move.w #$0001,d0
                 bra \Flagset
\FalseTrack:     move.w #$0002,d0
                 bra \Flagset
\NotDOSTrack:    move.w #$0017,d0
                 bra \Flagset
\HeaderFalse:    move.w #$001b,d0
                 bra \Flagset
\DataFalse:      move.w #$0019,d0
\Flagset:        move.w #ReadError,ErrorFlag
                 bra \CBEnd1

;compare Bytes read with old 
;>= A4 = Pointer to Base address of the old Block

FVerify:
               cmp #VerifyError,ErrorFlag
               beq \FVEnd2
               movem.l d2-d3/a2,-(a7)
               clr.l d3
               move.w BlockAdr,d3        ;Offset in Block
               move.l FTestAdr,a0        ;Address for test if 
                                         ;Block already loaded  
               move.l DecodeAdr,a2       ;Address, where comparison 
                                         ;is made
\FV1:          MOVE.W $DFF01E,D0
               BTST #1,D0                ;area already read 
               bne  \FVEnd               ;Yes, End
               tst.l (a0)                ;TestAdr
               beq \FV1                  ;Wait until Block was read
               move.w #$110,d2           ;comparison number
               move.w SectNum,d0
               sub.w FirstBlockSp,d0
               bcc \FV2
               addi.w #11,d0
\FV2:
               mulu #$440,d0
               move.l a4,a1            ;Base address for destination data
               add.l d0,a1             ;Address of the Block
\FV3:
               move.l (a2)+,d0
               cmp.l (a1,d3),d0
               beq \FV6                 ;Verify Ok
;test for special case ($aaaaaaaa and $2aaaaaaa)
               move.l (a1,d3),d1
               eor.l d1,d0
               cmp.l #$80000000,d0
               bne \FV5
\FV6:          addq.w #4,d3
               subq.w #1,d2
               bne \FV3
               adda.l #$440,a0           ;TestAdr
               clr.l d3                  ;Offset to Null
               add.w #1,SectNum          ;increment Sector number 
               cmp.w #$0b,SectNum        ;Number higher than 10?
               bcs \FV1                  ;No, OK
               clr.w SectNum             ;Number = 0
               bra \FV1
\FV5:          move.w #VerifyError,ErrorFlag
               bra \FVEnd3
\FVEnd:
               clr.w ErrorFlag
               move.w d3,BlockAdr
               move.l a2,DecodeAdr
               move.l a0,FTestAdr
\FVEnd3:       movem.l (a7)+,d2-d3/a2
\FVEnd2:       RTS

;code Track 
;>= A0 = Pointer to Source
;>= A1 = Pointer to Destination
;>= D0 = Track-Number
CodeTrack:
               movem.l d2-d4/a2-a3,-(a7)
               move.l d0,d4
               move.l a0,a2
               move.l a1,a3
               moveq #$0b,d2
               clr.w d3
\CT1:          move.w #$ff00,d0
               move.b d4,d0
               swap d0
               move.w d3,d0
               lsl.w #8,d0
               move.b d2,d0
               move.l a2,a0              ;Source
               move.l a3,a1              ;Destination
               bsr ConstructBlock
               add.l #$440,a3
               add.l #$200,a2
               addq.w #1,d3
               subq.w #1,d2
               bne \CT1
               movem.l (a7)+,d2-d4/a2-a3
               rts

;code Block and create Header 
;>= A0 = Uncoded Data (Source)
;>= A1 = Data buffer for coded Data (Destination)
;>= D0 = uncoded Header

ConstructBlock: MOVEM.L D2/A2/A4,-(A7)
               MOVEA.L A1,A4
               MOVEA.L A0,A2
               MOVE.L D0,D2
               MOVEQ #0,D0
               LEA 0(A4),A0
               BSR CodeLWord
               MOVE.L #$44894489,4(A4)
               MOVE.L D2,D0
               LEA 8(A4),A0
               BSR CodeLWord
               MOVEQ #3,D2
\EB1:          MOVEQ #0,D0
               BSR CodeLWord
               DBRA D2,\EB1
               LEA 8(A4),A0
               MOVEQ #$28,D1
               BSR TestSum
               LEA $30(A4),A0
               BSR CodeLWord
               MOVE.L #$200,D0
               MOVEA.L A2,A0
               LEA $40(A4),A1
               BSR CodeBlock
               LEA $40(A4),A0
               MOVE.W #$400,D1
               BSR TestSum
               LEA $38(A4),A0
               BSR CodeLWord
               MOVEM.L (A7)+,D2/A2/A4
               RTS

;code Data Block 
;>= D0 = Length of the Source
;>= A0 = Pointer to Source
;>= A1 = Pointer to Destination

CodeBlock:

               movem.l  d2/a5,-(a7)
               MOVE.W D0,D1
               LSL.W #2,D1
               ORI.W #8,D1
               MOVE.W D1,D2
               movem.l d0-d1/a0-a1/a5,-(a7)
               move.l a0,d1
               move.l a1,a5
               lea $dff000,a0
               bsr BlitWait
               bsr BlitterCode
               movem.l (a7)+,d0-d1/a0-a1/a5
               MOVE.L D0,D1
               MOVEA.L A1,A0
               BSR SetBorders
               ADDA.L D1,A0
               BSR SetBorders
               ADDA.L D1,A0
               BSR SetBorders
               movem.l (a7)+,d2/a5
               RTS

;A0 = $dff000
;D0 = Length of Source
;D1 = Source
;A5 = Destination

BlitterCode:
               bsr Modulu                ;set Mode 
               MOVE.L D1,$4C(A0)
               MOVE.L D1,$50(A0)
               MOVE.L A5,$54(A0)
               MOVE.W #$1DB1,$40(A0)
               MOVE.W #0,$42(A0)
               bsr StartBlit
               MOVE.L A5,$4C(A0)         ;Source B
               MOVE.L D1,$50(A0)         ;Source A
               MOVE.L A5,$54(A0)         ;Dest
               MOVE.W #$2d8c,$40(A0)
               bsr StartBlit
               movem.l d0-d1/a5,-(a7)
               ADD.L D0,D1
               SUBQ.L #2,D1
               ADDA.L D0,A5
               ADDA.L D0,A5
               SUBQ.L #2,A5
               MOVE.L D1,$4C(A0)
               MOVE.L D1,$50(A0)
               MOVE.L A5,$54(A0)
               MOVE.W #$DB1,$40(A0)
               MOVE.W #$1002,$42(A0)
               bsr StartBlit
               movem.l (a7)+,d0-d1/a5
               movem.l d0-d1/a5,-(a7)
               ADDA.L D0,A5
               MOVE.L A5,$4C(A0)
               MOVE.L D1,$50(A0)
               MOVE.L A5,$54(A0)
               MOVE.W #$1D8C,$40(A0)
               MOVE.W #0,$42(A0)
               bsr StartBlit
               movem.l (a7)+,d0-d1/a5
               rts

;start Blitter and wait for end of Blitter 

StartBlit:
               MOVE.W d2,$dff058
BlitWait:      btst #14,$dff002
               bne.s BlitWait
               rts

;set Mode for coding 
;>= A0 = $dff000
Modulu:
               movem.l d0/a1,-(a7)
               MOVEQ #0,D0
               LEA $44(A0),A1
               MOVE.L #-1,(A1)
               LEA $62(A0),A1
               MOVE.L D0,(A1)+
               MOVE.W D0,(A1)+
               ADDQ.L #8,A1
               MOVE.W #$5555,(A1)
               movem.l (a7)+,d0/a1
               rts

;erase Track with DOS 
;>= A0 = Pointer to Track-Buffer
DOSClear:
               move.l #$444F5300,d0      ;DOS + 0
               move.w #$57f,d1
\DO1:          move.l d0,(a0)+           ;erase Track 
               addq.b #1,d0
               dbf d1,\DO1
               rts

;shorten Track and store in memory 
;>= A0 = Pointer to beginning of Track
;>= A1 = Pointer to destination address
;>= Length = number of Bytes to be shortened
;>= ShrtByte = Byte, which should be stored shorter 
;=> A1 = Pointer to memory for shortened Block

Crunch:
               movem.l d2-d7/a2/a4,-(a7)
               clr.w d7
               clr.w d2
               move.w Length,d3      ;number of Bytes
               move.l MemoryLength,d6
\CHAnf:
               tst.w d7
               bne \CHEnd
               movea.l a0,a2         ;intermediate storage for Address 
\CH4:          bsr \EraseBlock
               tst.w d0
               beq \CHAnf
               move.b (a0),d4
               cmp.b ShrtByte,d4
               beq \KF1                  ;Null byte
               cmp.b 1(a0),d4
               bne \CH10                 ;no sequel 
               cmp.b 2(a0),d4
               beq \AF1                  ;other sequels 
\CH10:         addq.l #1,a0
               subq.w #1,d3
               bne \CH4                  ;continue search 
               bsr \NoResult
\CHEnd:
               move.b #$00,d0
               move.b d0,(a1)+
               subq.l #1,d6
               bcs CrunEnd
               move.l d6,MemoryLength
               move.l a1,MemoryBeg
               clr.l d0
               movem.l (a7)+,d2-d7/a2/a4
               rts
;short sequel 

\KF1:          cmp.b 1(a0),d4
               bne \CH10                 ;no Null 
               bsr \NoResult
               bsr CounterBytes
               cmp.w #$40,d1
               bcc \KF2                  ;too large for a Byte
               ori.b #ShrtNull,d1
               move.b d1,(a1)+
               subq.l #1,d6
               beq CrunEnd
               bra \KF4
\KF2:          cmp.w #$1000,d1
               bcc \KF3                  ;too large, must be Word
               move.w d1,d0
               lsr.w #8,d0
               ori.b #MiddleNull,d0      ;Null sequence with Byte
               move.b d0,(a1)+
               subq.l #1,d6
               beq CrunEnd
               move.b d1,(a1)+
               subq.l #1,d6
               beq CrunEnd
               bra \KF4
\KF3:          move.b #LongNull,d0
               move.b d0,(a1)+
               subq.l #1,d6
               beq CrunEnd
               move.w d1,d0
               lsr.w #8,d0
               move.b d0,(a1)+
               subq.l #1,d6
               beq CrunEnd
               move.b d1,(a1)+
               subq.l #1,d6
               beq CrunEnd
\KF4:          bra \CHAnf

;other sequence 

\AF1:          bsr \NoResult
               bsr CounterBytes
               cmp.w #$40,d1
               bcc \AF2                  ;too large for a Byte
               ori.b #ShrtNorm,d1
               move.b d1,(a1)+
               subq.l #1,d6
               beq CrunEnd
               bra \AF4
\AF2:          cmp.w #$1000,d1
               bcc \AF3                  ;too large, must be Word
               move.w d1,d0
               lsr.w #8,d0
               ori.b #MiddleNorm,d0      ;any sequence 
                                         ;Byte
               move.b d0,(a1)+
               subq.l #1,d6
               beq CrunEnd
               move.b d1,(a1)+
               subq.l #1,d6
               beq CrunEnd
               bra \AF4
\AF3:          move.b #LongNorm,d0
               move.b d0,(a1)+
               subq.l #1,d6
               beq CrunEnd
               move.w d1,d0
               lsr.w #8,d0
               move.b d0,(a1)+
               subq.l #1,d6
               beq CrunEnd
               move.b d1,(a1)+
               subq.l #1,d6
               beq CrunEnd
\AF4:          move.b d4,d0              ;store other Byte 
               move.b d0,(a1)+
               subq.l #1,d6
               beq CrunEnd
               bra \CHAnf

;found no sequence 
\NoResult2:  move.w #1,Subtr             ;See CrunEnd2
               bra \KF20
\NoResult:   clr.w Subtr
\KF20:         move.l a0,a4
               sub.l a2,a4
               move.w a4,d1
               beq \KFEnd
               swap d1
               move.w a4,d1
               cmp.w #$40,d1
               bcc \CH5                  ;too large for a Byte
               ori.b #ShrtNone,d1
               move.b d1,(a1)+
               subq.l #1,d6
               beq CrunEnd2
               bra \CH6
\CH5:          cmp.w #$1000,d1
               bcc \CH7                  ;too large, must be Word
               move.w d1,d0
               lsr.w #8,d0
               ori.b #MiddleNone,d0
               move.b d0,(a1)+
               subq.l #1,d6
               beq CrunEnd2
               move.b d1,(a1)+
               subq.l #1,d6
               beq CrunEnd2
               bra \CH6
\CH7:          move.b #LongNone,D0
               move.b d0,(a1)+
               subq.l #1,d6
               beq CrunEnd2
               move.w d1,d0
               lsr.w #8,d0
               move.b d0,(a1)+
               subq.l #1,d6
               beq CrunEnd2
               move.b d1,(a1)+
               subq.l #1,d6
               beq CrunEnd2
\CH6:          swap d1
               andi.l #$ffff,d1
               sub.l d1,d6
               beq CrunEnd2
               bcs CrunEnd2
               bra \CH8
\CH9:          move.b (a2)+,(a1)+
\CH8:          dbf d1,\CH9
\KFEnd:        clr.w Subtr               ;See CrunEnd2
               rts

\EraseBlock:
               move.w d3,d0
               andi.w #$fe00,d0
               cmp.w d0,d3
               bne \LBEnd2
               move.l a0,a3
               move.w #$7e,d5
               move.l (a0)+,d4
               move.l d4,d0
               andi.l #$ff000000,d0
               cmp.l #$44000000,d0
               bne \LBNone
\LB1:          addq.b #1,d4
               cmp.l (a0)+,d4
               bne \LBNone
               dbf d5,\LB1
               bsr \NoResult2
               move.b #EmptyBlock,d0
               move.b d0,(a1)+
               subq.l #1,d6
               beq CrunEnd2
               clr.w d0                  ;Ok-Message 
               subi.w #$200,d3
               bne \LBEnd
               move.w #-1,d7             ;End mark 
               bra \LBEnd
\LBNone:       move.l a3,a0
\LBEnd2:       move.w #-1,d0
\LBEnd:        rts

CounterBytes:    clr.w d1
\ZB2:          cmp.b (a0)+,d4
               bne \ZB1
               addq.w #1,d1
               subq.w #1,d3
               bne \ZB2
               move.w #-1,d7             ;End mark 
\ZB1:
               subq.l #1,a0
               rts



CrunEnd2:      move.w Subtr,d2
\CE1:          adda.l #$4,a7
               dbf d2,\CE1
CrunEnd:
               movem.l (a7)+,d2-d7/a2/a4
               move.l #-1,d0
               rts

;bring Track to normal size 
;>= A0 = Pointer to crunched Track
;>= A1 = Pointer to destination address

DeCrunch:
               move.b (a0)+,d0
               tst.b d0
               beq \DCEnd                ;End mark 
               move.b d0,d1
               andi.b #$c0,d1
               bne Shrt
               move.b d0,d1
               andi.b #$30,d1
               bne Middle
               move.b d0,d1
               cmpi.b #EmptyBlock,d1
               beq \BlockClear
               move.b (a0)+,d0
               lsl.w #8,d0
               move.b (a0)+,d0
               cmpi.b #LongNull,d1
               beq \NullLong
               cmpi.b #LongNorm,d1
               beq \NormLong
               cmpi.b #LongNone,d1
               beq \UndefLong
;error 
               move.l $4,a6
               sub.l a5,a5
               move.l #$12345678,d7
               jsr -108(a6)
\DCEnd:        rts


;empty Block
\BlockClear:    move.w #$7f,d1
               move.l #$444F5300,d0
\LB1:          move.l d0,(a1)+
               addq.b #1,d0
               dbf d1,\LB1
               bra DeCrunch
;Long 

\LA1:          move.b (a0)+,(a1)+
\UndefLong:    dbf d0,\LA1
               bra DeCrunch
\NullLong:     move.b Shrtbyte,d1
               bra \LA2
\NormLong:     move.b (a0)+,d1
               bra \LA2
\LA3:          move.b d1,(a1)+
\LA2:          dbf d0,\LA3
               bra DeCrunch
Shrt:
               cmpi.b #ShrtNull,d1
               beq \KU1
               cmpi.b #ShrtNorm,d1
               beq \KU2
;ShrtUndeff
               andi.w #$3f,d0
               bra \KU3
\KU4:          move.b (a0)+,(a1)+
\KU3:          dbf d0,\KU4
               bra DeCrunch
\KU1:          move.b Shrtbyte,d1
               bra \KU5
\KU2:          move.b (a0)+,d1
\KU5:          andi.w #$003f,d0
               bra \KU6
\KU7:          move.b d1,(a1)+
\KU6:          dbf d0,\Ku7
               bra DeCrunch
Middle:
               andi.w #$0f,d0
               lsl.w #8,d0
               move.b (a0)+,d0
               cmpi.b #MiddleNull,d1
               beq \KU1
               cmpi.b #MiddleNorm,d1
               beq \KU2
;MiddleUndeff
               bra \KU3
\KU4:          move.b (a0)+,(a1)+
\KU3:          dbf d0,\KU4
               bra DeCrunch
\KU1:          move.b Shrtbyte,d1
               bra \KU6
\KU2:          move.b (a0)+,d1
               bra \KU6
\KU7:          move.b d1,(a1)+
\KU6:          dbf d0,\Ku7
               bra DeCrunch

beg:
        move.w #$0008,$dff09a

        move.l gfxbase,a6
        lea    bitmap,a0
        move.b #1,d0
        move.w #320,d1
        move.w #200,d2         ;PAL uses 256
        jsr    InitBitMap(a6)
        move.l bit_adress,plane1
        move.l bit_adress,d1
        move.w d1,plane_lo
        swap   d1
        move.w d1,plane_hi

        lea    rastport,a1
        jsr    InitRastPort(a6)
        move.l #bitmap,r_bitmap

        move.l #ncopper,a0
        move.l cop_adress,a1
        move.l #copsize,d0
copy_loop:
        move.b (a0)+,(a1)+
        dbf    d0,copy_loop

        bsr  adresses
        move.l c1_adress,flash_adress

        move.l bit_adress,a0
        move.w #$27ff,d0
clear_loop:
        clr.b  (a0)+
        dbf    d0,clear_loop

        move.l gfxbase,a0
        move.w #$0080,$dff096
        move.l $6c,oldirq
        move.l #newirq,$6c
        move.l 50(a0),oldcopper
        move.l cop_adress,50(a0)
        move.w #$82b0,$dff096

new_start:
        move.w #7,x1
        move.w #54,y1
        move.b #$4f,lc
        move.b #$00,fc
        move.b #$03,tr
        move.b #$00,ws
        move.b #$01,vd
        move.b #$01,fa
        move.b #$00,dc1
        move.b #$00,dc2
        move.b #$01,sd
        move.b #$00,dd
        move.b #$01,sy
        move.b #$00,new
        move.b #$00,pointer1
        move.b #$00,color_ptr
        move.b drives,dd
        bsr  end_drive
        bsr  show_lc
        move.l #text1,text_ptr
        bsr  set_title
        bra  menu_control
exit:
        move.w #$8008,$dff09a
        move.l gfxbase,a0
        move.w #$0080,$dff096
        move.l oldirq,$6c
        move.l oldcopper,50(a0)
        move.w #$82b0,$dff096

no_DPuffer:
        move.l ExecBase,a6
        move.l cop_adress,a1
        move.l #copsize+2,d0
        jsr    FreeMem(a6)
no_copper:
        move.l ExecBase,a6
        move.l bit_adress,a1
        move.l #$2800,d0
        jsr    FreeMem(a6)
no_bitmap:
        move.l ExecBase,a6
        move.l gfxbase,a1
        jsr    CloseLibrary(a6)
no_gfxbase:
        clr.l  d0
        rts

newirq:
        move   SR,-(a7)
        movem.l a0-a6/d0-d7,-(a7)
        addq.b #1,waiting
        cmp.b  #2,waiting
        ble    endirq
        clr.b  waiting
        move.l flash_adress,a2
        cmpi.b #$00,color_ptr
        bne.s  irq_flash
        move.w #$00ee,(a2)
        bra.s  endirq
irq_flash:
        cmpi.b #$00,back
        beq.s  upward
downward:
        subi.w #$0011,(a2)
        cmpi.w #$0044,(a2)
        bcc.s  endirq
        move.b #$00,back
        bra.s  endirq
upward: addi.w #$0011,(a2)
        cmpi.w #$00ff,(a2)
        bcs.s  endirq
        move.b #$01,back
endirq: movem.l (a7)+,a0-a6/d0-d7
        move   (a7)+,SR
        dc.w $4ef9
oldirq: dc.l 0

menu_control:
        bsr  wait_key
        cmpi.b #$46,d0
        beq  destination_drive
        cmpi.b #$50,d0
        beq  start_copy
        cmpi.b #$51,d0
        beq  first_cylinder
        cmpi.b #$52,d0
        beq  last_cylinder
        cmpi.b #$53,d0
        beq  how_many_tries
        cmpi.b #$54,d0
        beq  write_serveral_times
        cmpi.b #$55,d0
        beq  verify_destination
        cmpi.b #$56,d0
        beq  fast_copy
        cmpi.b #$57,d0
        beq  deepcopy_1
        cmpi.b #$58,d0
        beq  deepcopy_2
        cmpi.b #$59,d0
        beq  source_drive
        cmpi.b #$21,d0
        beq  synccorrection
        bra.s  menu_control
start_copy:
        move.l c2_adress,flash_adress
        move.b #$01,color_ptr
        bsr  show_start
start_copy2:
        bsr  wait_key
        cmpi.b #$45,d0
        beq  new_start
        cmpi.b #$44,d0                   ;Return
        beq.s  end_start
        cmpi.b #$43,d0
        bne.s  start_copy2
end_start:
        move.b #$00,color_ptr
        move.w #28,y1
        bsr    cl2
        move.w #10,d0
estlop: bsr    Timer
        dbf    d0,estlop
        bsr clear_eol
        bsr copy_start                   ;Copy-Routine
        cmp.w #Escape,ErrorFlag
        beq new_start
        cmp.w #diskprotect,errorflag
        beq start_copy
        cmp.w #NoDisk,errorflag
        beq start_copy
        cmp.w #NotProtect,ErrorFlag
        beq.s start_copy
        bsr  cl1
esd1:   bsr  wait_key
        cmpi.b #$40,d0
        bne.s  esd1
esd2:   bra new_start

destination_drive:
        move.l c13_adress,flash_adress
        move.b #$01,color_ptr
destination1:
        bsr  wait_key
        cmpi.b #$0a,d0
        beq.s  d_drive0
        cmpi.b #$01,d0
        beq.s  d_drive1
        cmpi.b #$02,d0
        beq  d_drive2
        cmpi.b #$03,d0
        beq  d_drive3
        cmpi.b #$43,d0
        beq.s  end_destination
        cmpi.b #$44,d0
        bne.s  destination1
end_destination:
        cmpi.b #$00,dd
        beq.s  destination1
        move.b #$00,color_ptr
        bra  menu_control
d_drive0:
        btst   #0,drives
        beq  end_drive
        btst   #0,dd
        beq.s  dd0_0
        bclr   #0,dd
        bra.s  dd0_1
dd0_0:  bset   #0,dd
        move.b #1,drv
dd0_1:  bra  end_drive

d_drive1:
        btst   #1,drives
        beq  end_drive
        btst   #1,dd
        beq.s  dd1_0
        bclr   #1,dd
        bra.s  dd1_1
dd1_0:  bset   #1,dd
        move.b #2,drv
dd1_1:  bra.s  end_drive

d_drive2:
        btst   #2,drives
        beq.s  end_drive
        btst   #2,dd
        beq.s  dd2_0
        bclr   #2,dd
        bra.s  dd2_1
dd2_0:  bset   #2,dd
        move.b #4,drv
dd2_1:  bra.s  end_drive

d_drive3:
        btst   #3,drives
        beq.s  end_drive
        btst   #3,dd
        beq.s  dd3_0
        bclr   #3,dd
        bra.s  end_drive
dd3_0:  bset   #3,dd
        move.b #8,drv
end_drive:
        cmpi.b #$01,dc1
        bne.s  st1
        bra.s  st2
st1:    cmpi.b #$01,dc2
        bne  steve1
st2:    move.b drv,dd
        bra  steve
steve1: btst   #0,sd
        beq.s  ste1
        andi.b #$0e,dd
        cmpi.b #$00,dd
        bne.s  steve
        bset   #0,dd
        bra.s  steve
ste1:   btst   #1,sd
        beq.s  ste2
        andi.b #$0d,dd
        cmpi.b #$00,dd
        bne.s  steve
        bset   #1,dd
        bra.s  steve
ste2:   btst   #2,sd
        beq.s  ste3
        andi.b #$0b,dd
        cmpi.b #$00,dd
        bne.s  steve
        bset   #2,dd
        bra.s  steve
ste3:   btst   #3,sd
        beq.s  steve
        andi.b #$07,dd
        cmpi.b #$00,dd
        bne.s  steve
        bset   #3,dd
steve:  btst   #0,dd
        bne.s  end_dd1
        lea    off_text,a0
        bra.s  end_dd2
end_dd1:lea    on_text2,a0
end_dd2:bsr  set_drive0
        btst   #1,dd
        bne.s  end_dd3
        lea    off_text,a0
        bra.s  end_dd4
end_dd3:lea    on_text2,a0
end_dd4:bsr  set_drive1
        btst   #2,dd
        bne.s  end_dd5
        lea    off_text,a0
        bra.s  end_dd6
end_dd5:lea    on_text2,a0
end_dd6:bsr  set_drive2
        btst   #3,dd
        bne.s  end_dd7
        lea    off_text,a0
        bra.s  end_dd8
end_dd7:lea    on_text2,a0
end_dd8:bsr  set_drive3
        cmpi.b #$00,pointer1
        bne.s  end_dd9
        move.b #$01,pointer1
        rts
end_dd9:bra  destination1

set_drive0:
        move.l gfxbase,a6
        lea    rastport,a1
        move.w #61,d0
        move.w #190,d1         ;PAL 213
        jsr    Movee(a6)
        bra.s  set_text
set_drive1:
        move.l gfxbase,a6
        lea    rastport,a1
        move.w #126,d0
        move.w #190,d1         ;PAL 213
        jsr    Movee(a6)
        bra.s  set_text
set_drive2:
        move.l gfxbase,a6
        lea    rastport,a1
        move.w #190,d0
        move.w #190,d1         ;PAL 213
        jsr    Movee(a6)
        bra.s  set_text
set_drive3:
        move.l gfxbase,a6
        lea    rastport,a1
        move.w #254,d0
        move.w #190,d1         ;PAL 213
        jsr    Movee(a6)
set_text:
        lea    rastport,a1
        move.w #$0003,d0
        jsr    Textout(a6)
        rts

first_cylinder:
        move.l c3_adress,flash_adress
        move.b #$01,color_ptr
        bsr  wait_key
        cmpi.b #$4f,d0
        beq.s  fc_down
        cmpi.b #$4e,d0
        beq.s  fc_up
        cmpi.b #$43,d0
        beq  compare_fc
        cmpi.b #$44,d0
        bne.s  first_cylinder
compare_fc:
        move.b lc,d0
        cmp.b fc,d0
        beq  compare_fc2
        blt.s  first_cylinder
compare_fc2:
        move.b #$00,color_ptr
        bra  menu_control
fc_down:subi.b #$01,fc
        cmpi.b #$ff,fc
        bne.s  fc_down2
        move.b #$00,fc
fc_down2:
        bra  show_fc
fc_up:  addi.b #$01,fc
        cmpi.b #$52,fc
        bne.s  fc_down2
        move.b #$51,fc
show_fc:lea    fc_text,a0
        move.b fc,d0
        bsr  byte_calculate
        move.l gfxbase,a6
        lea    rastport,a1
        move.w #295,d0
        move.w #64,d1
        jsr    Movee(a6)
        lea    rastport,a1
        lea    fc_text,a0
        move.w #$0002,d0
        jsr    Textout(a6)
        bra  first_cylinder

last_cylinder:
        move.l c4_adress,flash_adress
        move.b #$01,color_ptr
        bsr  wait_key
        cmpi.b #$4f,d0
        beq.s  lc_down
        cmpi.b #$4e,d0
        beq.s  lc_up
        cmpi.b #$43,d0
        beq  compare_lc
        cmpi.b #$44,d0
        bne.s  last_cylinder
compare_lc:
        move.b fc,d0
        cmp.b lc,d0
        beq  compare_lc2
        bge.s  last_cylinder
compare_lc2:
        move.b #$00,color_ptr
        bra  menu_control
lc_down:subi.b #$01,lc
        cmpi.b #$ff,lc
        bne.s  lc_down2
        move.b #$00,lc
lc_down2:
        bra  lcc
lc_up:  addi.b #$01,lc
        cmpi.b #$52,lc
        bne.s  lc_down2
        move.b #$51,lc
lcc:    bsr.s  show_lc
        bra  last_cylinder
show_lc:lea    lc_text,a0
        move.b lc,d0
        bsr  byte_calculate
        move.l gfxbase,a6
        lea    rastport,a1
        move.w #295,d0
        move.w #74,d1
        jsr    Movee(a6)
        lea    rastport,a1
        lea    lc_text,a0
        move.w #$0002,d0
        jsr    Textout(a6)
        rts

how_many_tries:
        move.l c5_adress,flash_adress
        move.b #$01,color_ptr
tries1: lea    tr_text,a0
        bsr  wait_key
        cmpi.b #$4e,d0
        beq.s  tries_up
        cmpi.b #$4f,d0
        beq.s  tries_down
        cmpi.b #$43,d0
        beq.s  end_tries
        cmpi.b #$44,d0
        bne.s  tries1
end_tries:
        move.b #$00,color_ptr
        bra  menu_control
tries_up:
        addi.b #$01,tr
        cmpi.b #$0a,tr
        bne.s  tries_up2
        move.b #$09,tr
tries_up2:
        move.b tr,d0
        addi.w #$30,d0
        move.b d0,(a0)
        bra.s  tries2
tries_down:
        subi.b #$01,tr
        cmpi.b #$00,tr
        bne.s  tries_down2
        move.b #$01,tr
tries_down2:
        move.b tr,d0
        addi.w #$30,d0
        move.b d0,(a0)
tries2: move.l gfxbase,a6
        lea    rastport,a1
        move.w #303,d0
        move.w #84,d1
        jsr    Movee(a6)
        lea    rastport,a1
        lea    tr_text,a0
        move.w #$0001,d0
        jsr    Textout(a6)
        bra  tries1

synccorrection:
        move.l c12_adress,flash_adress
        move.b #$01,color_ptr
        cmpi.b #$01,sy
        bne.s  sync2
        clr.b  sy
        lea    off_text,a0
        bra.s  sync3
sync2:  move.b #$01,sy
        lea    on_text,a0
sync3:  lea    rastport,a1
        move.w #287,d0
        move.w #157,d1
        jsr    Movee(a6)
        lea    rastport,a1
        move.w #3,d0
        jsr    Textout(a6)
        move.b #$00,color_ptr
        bra  menu_control

write_serveral_times:
        move.l c6_adress,flash_adress
        move.b #$01,color_ptr
        move.b sd,d0
        cmp.b dd,d0
        bne  wait_return
        cmpi.b #$00,ws
        bne.s  write_s2
write_s1:
        move.b #$01,ws
        lea    on_text,a0
        bra.s  end_write_serveral
write_s2:
        move.b #$00,ws
        lea    off_text,a0
end_write_serveral:
        move.l gfxbase,a6
        lea    rastport,a1
        move.w #287,d0
        move.w #94,d1
        jsr    Movee(a6)
        lea    rastport,a1
        move.w #$0003,d0
        jsr    Textout(a6)
esw:    move.b #$00,color_ptr
        bra  menu_control

verify_destination:
        move.b dc1,d0
        or.b dc2,d0
        tst.b d0
        bne menu_control
        move.l c7_adress,flash_adress
        move.b #$01,color_ptr
        cmpi.b #$00,vd
        bne.s  verify_d2
verify_d1:
        move.b #$01,vd
        lea    on_text,a0
        bra.s  end_verify
verify_d2:
        move.b #$00,vd
        lea    off_text,a0
end_verify:
        bsr verify_d3
        bra  menu_control
verify_off:
        move.b #$00,vd
        lea    off_text,a0
verify_d3:
        move.l gfxbase,a6
        lea    rastport,a1
        move.w #287,d0
        move.w #104,d1
        jsr    Movee(a6)
        lea    rastport,a1
        move.w #$0003,d0
        jsr    Textout(a6)
        move.b #$00,color_ptr
        rts

fast_copy:
        move.l c8_adress,flash_adress
        move.b #$01,color_ptr
        cmpi.b #$01,dd
        beq.s  fcop1
        cmpi.b #$02,dd
        beq.s  fcop1
        cmpi.b #$04,dd
        beq.s  fcop1
        cmpi.b #$08,dd
        beq.s  fcop1
        bra  wait_return
fcop1:  cmpi.b #$01,fa
        bne.s  fastcopy1
        move.b #$00,fa
        move.b #$01,dc1
        move.b #$00,dc2
        bra.s  end_fast
fastcopy1:
        move.b #$01,fa
        move.b #$00,dc1
        move.b #$00,dc2
end_fast:
        cmp.b #ON,DC1
        bne fcop2
        bsr verify_off
fcop2:  bsr  show_copies
        move.b #$00,color_ptr
        bra  menu_control

deepcopy_1:
        bsr verify_off
        move.l c9_adress,flash_adress
        move.b #$01,color_ptr
        cmpi.b #$01,dd
        beq.s  deep4
        cmpi.b #$02,dd
        beq.s  deep4
        cmpi.b #$04,dd
        beq.s  deep4
        cmpi.b #$08,dd
        beq.s  deep4
        bra.s  wait_return
deep4:  cmpi.b #$00,dc1
        beq.s  deep1
        move.b #$00,fa
        move.b #$00,dc1
        move.b #$01,dc2
        bra.s  end_deep1
deep1:  move.b #$00,fa
        move.b #$01,dc1
        move.b #$00,dc2
end_deep1:
        bra  end_fast

wait_return:
        move.l #text12,text_ptr
        move.w #16,x1
        move.w #28,y1
        bsr    set_text3
wait_r3:bsr    wait_key
        cmpi.b #$44,d0
        beq.s  wait_r2
        cmpi.b #$43,d0
        bne.s  wait_return
wait_r2:
        bsr    BegText
        bra    end_fast
wait_r4:bsr    wait_key
        cmpi.b #$45,d0
        beq.s  wait_r5
        cmpi.b #$44,d0
        beq    \W1
        cmpi.b #$43,d0
        beq    \W1
        cmpi.b #$40,d0
        bne.s  wait_r4
\W1:    move.l d0,-(a7)
        bsr    clear_eol
        move.l (a7)+,d0
        clr.l  d0
        rts
wait_r5:move.l #-1,d0
        move.w #Escape,ErrorFlag
        rts

deepcopy_2:
        bsr    verify_off
        move.l c10_adress,flash_adress
        move.b #$01,color_ptr
        cmpi.b #$01,dd
        beq.s  deep3
        cmpi.b #$02,dd
        beq.s  deep3
        cmpi.b #$04,dd
        beq.s  deep3
        cmpi.b #$08,dd
        beq.s  deep3
        bra    wait_return
deep3:  cmpi.b #$01,dc2
        beq.s  deep2
        move.b #$00,fa
        move.b #$00,dc1
        move.b #$01,dc2
        bra.s  end_deep2
deep2:  move.b #$01,fa
        move.b #$00,dc1
        move.b #$00,dc2
end_deep2:
        bra    end_fast
show_copies:
        move.l gfxbase,a6
        lea    rastport,a1
        move.w #287,d0
        move.w #114,d1
        jsr    Movee(a6)
        lea    rastport,a1
        cmpi.b #$00,fa
        beq.s  show1
        lea    on_text,a0
        bra.s  show2
show1:  lea    off_text,a0
show2:  move.w #$0003,d0
        jsr    Textout(a6)
        lea    rastport,a1
        move.w #287,d0
        move.w #124,d1
        jsr    Movee(a6)
        lea    rastport,a1
        cmpi.b #$00,dc1
        beq.s  show3
        lea    on_text,a0
        bra.s  show4
show3:  lea    off_text,a0
show4:  move.w #$0003,d0
        jsr    Textout(a6)
        lea    rastport,a1
        move.w #287,d0
        move.w #134,d1
        jsr    Movee(a6)
        lea    rastport,a1
        cmpi.b #$00,dc2
        beq.s  show5
        lea    on_text,a0
        bra.s  show6
show5:  lea    off_text,a0
show6:  move.w #$0003,d0
        jsr    Textout(a6)
        rts

source_drive:
        move.l c11_adress,flash_adress
        move.b #$01,color_ptr
source1:
        bsr    wait_key
        cmpi.b #$0a,d0
        beq.s  s_drive0
        cmpi.b #$01,d0
        beq.s  s_drive1
        cmpi.b #$02,d0
        beq    s_drive2
        cmpi.b #$03,d0
        beq    s_drive3
        cmpi.b #$43,d0
        beq.s  source2
        cmpi.b #$44,d0
        bne.s  source1
source2:move.b pointer1,d7
        clr.b  pointer1
        bsr    end_drive
        move.b d7,pointer1
        move.b #$00,color_ptr
        bra    menu_control
s_drive0:
        btst   #$00,drives
        beq    source1
s_dd0:  move.b #$01,sd
        move.b #$00,d0
        bra    set_s_drive
s_drive1:
        btst   #$01,drives
        beq    source1
s_dd1:  move.b #$02,sd
        move.b #$01,d0
        bra    set_s_drive
s_drive2:
        btst   #$02,drives
        beq    source1
s_dd2:  move.b #$04,sd
        move.b #$02,d0
        bra.s  set_s_drive
s_drive3:
        btst   #$03,drives
        beq    source1
        move.b #$08,sd
s_dd3:  move.b #$03,d0
set_s_drive:
        lea    sd_text,a0
        addi.b #$30,d0
        move.b d0,(a0)
        move.l gfxbase,a6
        lea    rastport,a1
        move.w #303,d0
        move.w #144,d1
        jsr    movee(a6)
        lea    rastport,a1
        move.w #$0001,d0
        jsr    Textout(a6)
        bra    source1

byte_calculate:
        cmpi.w #$0a,d0
        bmi.s  byte2
        divu   #$0a,d0
        move.w d0,d1
        addi.w #$30,d1
        swap   d0
        bra.s  byte3
byte2:  move.w #$0030,d1
byte3:  move.b d1,(a0)+
        addi.w #$0030,d0
        move.b d0,(a0)+
        rts

adresses:
        move.l cop_adress,d0
        move.l #color1,d1
        move.l #ncopper,d2
        sub.l  d2,d1
        add.l  d1,d0
        move.l d0,c1_adress
        addi.l #$000010,d0
        move.l d0,c2_adress
        addi.l #$000008,d0
        move.l d0,c3_adress
        addi.l #$000008,d0
        move.l d0,c4_adress
        addi.l #$000008,d0
        move.l d0,c5_adress
        addi.l #$000008,d0
        move.l d0,c6_adress
        addi.l #$000008,d0
        move.l d0,c7_adress
        addi.l #$000008,d0
        move.l d0,c8_adress
        addi.l #$000008,d0
        move.l d0,c9_adress
        addi.l #$000008,d0
        move.l d0,c10_adress
        addi.l #$000008,d0
        move.l d0,c11_adress
        addi.l #$000008,d0
        move.l d0,c12_adress
        addi.l #$000010,d0
        move.l d0,c13_adress
        rts

set_title:
        clr.l  d6
        move.w #$0009,d6
set_text1:
        move.l gfxbase,a6
        bsr    set_text2
        addi.l #$000026,text_ptr
        addi.w #$000a,y1
        dbf    d6,set_text1
        lea    floppy,a0
        move.l bit_adress,a1
        add.l  #$001c26,a1
        move.l a1,a2
        bsr.s  box
        lea    floppy,a0
        move.l a1,a2
        add.l  #$000008,a2
        bsr.s  box
        lea    floppy,a0
        move.l a1,a2
        add.l  #$000010,a2
        bsr.s  box
        lea    floppy,a0
        move.l a1,a2
        add.l  #$000018,a2
        bsr.s  box
        bra.s  set_work
box:    rts                    ;Remove this rts for PAL systems
        move.w #floppy_s,d0    ;will draw graphic disk drive onscreen
bit_copy_loop:
        move.b (a0)+,(a2)+
        move.b (a0)+,(a2)+
        move.b (a0)+,(a2)+
        move.b (a0)+,(a2)+
        move.b (a0)+,(a2)+
        move.b (a0)+,(a2)+
        add.l  #$22,a2
        dbf    d0,bit_copy_loop
        rts
set_work:
        move.w #44,y2
        bsr    draw_line
        move.w #148,y2
        bsr    draw_line
        move.w #218,y2
        bsr    draw_line
        move.w #250,y2
        bsr    draw_line
        move.w #160,y2
        bsr    draw_line
        move.w #157,y1
        move.l #text11,text_ptr
        bsr    set_text2
        move.w #170,y1
        move.w #$0001,d2
        move.l #text2,text_ptr
set_loop2:
        bsr    set_text2
        addi.l #$000026,text_ptr
        addi.w #$000a,y1
        dbf    d2,set_loop2
        move.w #$0001,d2
        move.l #text3,text_ptr
        move.w #200,y1          ;PAL uses 230

        bsr    set_text2;         ;added to NTSC
        move.l #text3a,text_ptr ;added to NTSC
        move.w #7,x1            ;to position text
        move.w #210,y1          ;PAL uses 245


set_loop3:
        bsr    set_text2
        addi.w #$000f,y1
        addi.l #$000026,text_ptr
        dbf    d2,set_loop3
        lea    rastport,a1
        move.b #1,d0
        jsr    SetAPen(a6)
        lea    rastport,a1
        move.w #10,d0
        move.w #10,d1
        move.w #309,d2
        move.w #40,d3
        jsr    RectFill(a6)
        lea    rastport,a1
        move.b #0,d0
        jsr    SetAPen(a6)
        lea    rastport,a1
        move.w #11,d0
        move.w #11,d1
        move.w #308,d2
        move.w #39,d3
        jsr    RectFill(a6)
        lea    rastport,a1
        move.b #1,d0
        jsr    SetAPen(a6)
BegText: move.l #text4,text_ptr
        move.w #16,x1
        move.w #18,y1
        bsr    set_text3
        move.l #text20,text_ptr
        move.w #28,y1
        bsr    set_text3
        move.l #text21,text_ptr
        move.w #38,y1
        bsr    set_text3
        rts

draw_line:
        lea    rastport,a1
        move.w #$0000,d0
        move.w y2,d1
        jsr    Movee(a6)
        lea    rastport,a1
        move.w #$013f,d0
        move.w y2,d1
        jsr    Draw(a6)
        rts

set_text2:
        move.l a6,-(a7)
        move.l gfxbase,a6
        lea    rastport,a1
        move.w x1,d0
        move.w y1,d1
        jsr    Movee(a6)
        lea    rastport,a1
        move.l text_ptr,a0
        move.w #$0026,d0
        jsr    Textout(a6)
        move.l (a7)+,a6
        rts

set_text3:
        move.l a6,-(a7)
        move.l gfxbase,a6
        lea    rastport,a1
        move.w x1,d0
        move.w y1,d1
        jsr    Movee(a6)
        lea    rastport,a1
        move.l text_ptr,a0
        move.w #$0024,d0
        jsr    Textout(a6)
        move.l (a7)+,a6
        rts

show_start:
        lea    text6,a0
        btst   #0,dd
        bne    show_s1
        btst   #0,sd
        beq.s  show_start1
show_s1:lea    df0,a1
        bsr    copy_drives
show_start1:
        btst   #1,dd
        bne.s  show_s2
        btst   #1,sd
        beq.s  show_start2
show_s2:lea    df1,a1
        bsr    copy_drives
show_start2:
        btst   #2,dd
        bne.s  show_s3
        btst   #2,sd
        beq.s  show_start3
show_s3:lea    df2,a1
        bsr.s  copy_drives
show_start3:
        btst   #3,dd
        bne.s  show_s4
        btst   #3,sd
        beq.s  show_start4
show_s4:lea    df3,a1
        bsr.s  copy_drives
show_start4:
        move.w #16,x1
        move.w #18,y1
        move.w #$002,d2
        move.l #text5,text_ptr
show_loop:
        bsr    set_text3
        addi.w #$000a,y1
        addi.l #$000024,text_ptr
        dbf    d2,show_loop
        move.w #16,d0
        lea    text6,a0
lop:    move.b #$20,(a0)+
        dbf    d0,lop
        rts

copy_drives:
        move.w #$0003,d0
copy_d_loop:
        move.b (a1)+,(a0)+
        dbf    d0,copy_d_loop
        rts

read_error:
        clr.l  d0
        move.b cylinder,d0
        lea    text7,a0
        add.l  #$00001a,a0
        bsr    byte_calculate
        move.b side,d0
        add.l  #$000006,a0
        bsr    byte_calculate
        move.w #7,x1
        move.w #200,y1         ;PAL uses 230
        move.l #text7,text_ptr
        bra    set_text2

write_error:
        clr.l  d0
        move.b cylinder,d0
        lea    text8,a0
        add.l  #$00001b,a0
        bsr    byte_calculate
        move.b side,d0
        add.l  #$000006,a0
        bsr    byte_calculate
        move.w #7,x1
        move.w #200,y1         ;PAL uses 230
        move.l #text8,text_ptr
        bra    set_text2

clear_error:
        move.l #text3,text_ptr
        move.w #7,x1
        move.w #200,y1      ;PAL uses 230
        bra    set_text2
 
        move.l #text3a,text_ptr ;added to NTSC
        move.w #7,x1            ;to position text
        move.w #210,y1          ;(PAL uses 245)
        bra    set_text2          ;on the screen


reading_cyl:
        clr.l  d0
        move.b cylinder,d0
        lea    rcyl_text,a0
        bsr    byte_calculate
        lea    rcyl_text,a0
        move.l gfxbase,a6
        lea    rastport,a1
        move.w #127,d0
        move.w #210,d1         ;PALS uses 245
        jsr    Movee(a6)
        lea    rastport,a1
        move.w #$0002,d0
        jsr    Textout(a6)
        rts
writing_cyl:
        clr.l  d0
        move.b cylinder,d0
        lea    wcyl_text,a0
        bsr    byte_calculate
        lea    wcyl_text,a0
        move.l gfxbase,a6
        lea    rastport,a1
        move.w #271,d0
        move.w #210,d1         ;PAL uses 245
        jsr    Movee(a6)
        lea    rastport,a1
        move.w #$0002,d0
        jsr    Textout(a6)
        rts

insert_source:
        move.l #text9,text_ptr
        bra.s  melvin
insert_destination:
        move.l #text10,text_ptr
        bra.s  melvin
protect_source:
        bsr  cl
        move.l #text13,text_ptr
        bra.s  melvin
protect_destination:
        bsr  cl
        move.l #text14,text_ptr
melvin:
        move.w #16,x1
        move.w #28,y1
        bsr    set_text3
        move.l #text5,text_ptr
        move.w #18,y1
        bsr    set_text3
        bra    wait_r4
clear_eol:
        move.l #text15,text_ptr
        move.w #16,x1
        move.w #28,y1
        bsr    set_text3
        move.w #18,y1
        bra    set_text3

write_b_again:
        bsr  cl
        move.l #text17,text_ptr
        move.w #16,x1
        move.w #28,y1
        bsr    set_text3
wba1:   bsr    wait_key
        cmpi.b #$45,d0   ;check esc
        beq.s  wba4
        cmpi.b #$15,d0   ;German keyboards use 31 y and z reversed
        beq.s  wba2
        cmpi.b #$36,d0   ;check n
        bne.s  wba1
        move.l #-1,d0
        bra.s  wba3
wba2:   clr.l  d0
wba3:   move.l d0,-(a7)
        bsr    clear_eol
        move.l (a7)+,d0
        rts
wba4:   move.w #escape,errorflag
        rts

compare_drives:
        move.w #18,y1
        bsr    cl2
        lea    text19,a0
        clr.w  d2
cdl1:   lea    df0,a1
        btst   d2,vererrflag
        beq.s  cdl4
        move.w d2,d0
        lsl    #2,d0
        add.l  d0,a1
        bsr.s  cdl2
cdl4:   addq.w #1,d2
        cmpi.w #4,d2
        bne.s  cdl1
        move.l #text18,text_ptr
        move.w #28,y1
        bra    set_text3
cdl2:   move.w #3,d1
cdl3:   move.b (a1)+,(a0)+
        dbf    d1,cdl3
        rts

wait_key:
        movem.l d1-d7,-(a7)
        move.w Keybrdclr,d1
l8:     move.b IntCon,d0
        btst   #7,d1
        bne    l1
        sub.l  #1,Keybrdcnt
        beq    Keybrepeat
l1:     btst   #3,d0
        beq    l8
        move.b Key,d0
        ori.b  #$40,Cont
        not.b  d0
        ror.b  #1,d0
        move.w #$600,d1
l5:     dbf    d1,l5
        andi.b #$bf,Cont
        move.l #MaxWait,Cntwait
        move.l #MaxWait,Keybrdcnt
        move.w d0,Keybrdclr
Keybtdend:
        movem.l (a7)+,d1-d7
        rts
Keybrepeat:
        move.l Cntwait,d1
        cmp.l  #MinWait,d1
        bcs.s  repeat1
        sub.l  #$800,d1
        move.l d1,Cntwait
repeat1:move.l d1,Keybrdcnt
        move.w Keybrdclr,d0
        bra.s  Keybtdend

get_key:
        move.w $dff01e,d1
        btst   #3,d1
        beq    \l1
        move.b Key,d0
        ori.b  #$40,Cont
        not.b  d0
        ror.b  #1,d0
        move.w #$600,d1
\l2:    dbf    d1,\l2
        andi.b #$bf,Cont
\l1:    rts

cl:     move.w #28,y1
cl2:    move.w #16,x1
        move.l #text15,text_ptr
        bsr    set_text3
        addi.w #10,y1
        bsr    set_text3
        rts

cl1:    bsr.s  cl
        move.w #18,y1
        bsr    set_text3
        move.w #28,y1
        move.l #text16,text_ptr
        bsr    set_text3
        rts


gfxname:
         dc.b "graphics.library",0
         align.w
gfxbase:        dc.l 0
oldcopper:      dc.l 0
bit_adress:     dc.l 0
cop_adress:     dc.l 0
c1_adress:      dc.l 0
c2_adress:      dc.l 0
c3_adress:      dc.l 0
c4_adress:      dc.l 0
c5_adress:      dc.l 0
c6_adress:      dc.l 0
c7_adress:      dc.l 0
c8_adress:      dc.l 0
c9_adress:      dc.l 0
c10_adress:     dc.l 0
c11_adress:     dc.l 0
c12_adress:     dc.l 0
c13_adress:     dc.l 0

rastport:       blk.l  1,0
r_bitmap:       blk.l 24,0

bitmap:         blk.l  2,0
plane1:         blk.l  8,0

ncopper:
                dc.w $008e,$2681,$0090,$24c1
                dc.w $0092,$0038,$0094,$00d0
                dc.w $00e0
plane_hi:       dc.w $0000,$00e2
plane_lo:       dc.w $0000
                dc.w $0100,$1200,$0102,$0000,$0104,$0000
                dc.w $0108,$0000,$010a,$0000
                dc.w $0120,$0000,$0122,$0000
                dc.w $0180,$0000,$0182
color1:         dc.w $00ee,$0d01,$fffe,$0182
                dc.w $00ee,$5401,$fffe,$0182
color2:         dc.w $00ee,$6001,$fffe,$0182
color3:         dc.w $00ee,$6a01,$fffe,$0182
color4:         dc.w $00ee,$7201,$fffe,$0182
color5:         dc.w $00ee,$7d01,$fffe,$0182
color6:         dc.w $00ee,$8601,$fffe,$0182
color7:         dc.w $00ee,$9001,$fffe,$0182
color8:         dc.w $00ee,$9a01,$fffe,$0182
color9:         dc.w $00ee,$a401,$fffe,$0182
color10:        dc.w $00ee,$af01,$fffe,$0182
color11:        dc.w $00ee,$b701,$fffe,$0182
color12:        dc.w $00ee,$c501,$fffe,$0182
                dc.w $00ee,$c701,$fffe,$0182
color13:        dc.w $00ee,$ff01,$fffe,$0182
                dc.w $00ee,$ffff,$fffe
                dc.w $0000,$0000
copend:
copsize = copend - ncopper

drives:         dc.b 0
d_drives:       dc.b 0
s_drives:       dc.b 0
color_ptr:      dc.b 0
back:           dc.b 0
pointer1:       dc.b 0
cylinder:       dc.b 0
side:           dc.b 0
new:            dc.b 0
drv:            dc.b 0
       align.w
flash_adress:   dc.l 0
text_ptr:       dc.l 0

x1:             dc.w 7
y1:             dc.w 54
y2:             dc.w 0

keybrdclr:      dc.w $ffff
cntwait:        dc.l MaxWait
keybrdcnt:      dc.l MaxWait

fc_text:        dc.b "00"
ralf:           dc.b 0
lc_text:        dc.b "79"
tr_text:        dc.b "0"
sd_text:        dc.b "0"
rcyl_text:      dc.b "00"
wcyl_text:      dc.b "00"
on_text:        dc.b ".ON"
on_text2:       dc.b " ON"
off_text:       dc.b "OFF"
df0:            dc.b "DF0 "
df1:            dc.b "DF1 "
df2:            dc.b "DF2 "
df3:            dc.b "DF3 "

text1:  dc.b "F1  = START COPY......................"
        dc.b "F2  = FIRST CYLINDER (CRSR).........00"
        dc.b "F3  = LAST  CYLINDER (CRSR).........79"
        dc.b "F4  = HOW MANY TRIES (CRSR)..........3"
        dc.b "F5  = WRITE SEVERAL TIMES..........OFF"
        dc.b "F6  = VERIFY DESTINATION............ON"
        dc.b "F7  = FASTCOPY......................ON"
        dc.b "F8  = DEEPCOPY 1...................OFF"
        dc.b "F9  = DEEPCOPY 2...................OFF"
        dc.b "F10 = SOURCE DRIVE (0/1/2/3).......DF0"
text2:  dc.b "DEL = DESTINATION DRIVE (0/1/2/3)....."
        dc.b "      DF0:    DF1:    DF2:    DF3:    "
text3:  dc.b "         STATUS: 00, OK,00,00         "
text3a: dc.b "  READING CYL. 00 / WRITING CYL. 00   "
;text3a added for text positioning on NTSC systems
text4:  dc.b "       A M I G A - COPY  V1.2       "
text5:  dc.b "        (ESC) TERMINATES COPY       "
        dc.b "INSERT DISK(S) IN  "
text6:  dc.b "                 "
        dc.b "PRESS RETURN OR ENTER WHEN READY !¡!"
text7:  dc.b "STATUS: READ-ERROR ON CYL.00 SIDE 00  "
text8:  dc.b "STATUS: WRITE-ERROR ON CYL.00 SIDE 00 "
text9:  dc.b "    PLEASE INSERT SOURCE DISK !!    "
text10: dc.b "  PLEASE INSERT DESTINATION DISK !  "
text11: dc.b " S  = SYNC-CORRECTION...  ..........ON"
text12: dc.b "       ONLY ONE DESTINATION !!      "
text13: dc.b " SOURCE DISK INSN'T WRITE PROTECTED."
text14: dc.b "DESTINATION DISK IS WRITE PROTECTED."
text15: dc.b "                                    "
text16: dc.b "          COPY COMPLETE !!          "
text17: dc.b "    WRITE BUFFER AGAIN ??? (Y/N)    "
text18: dc.b " ERROR ON DRIVE(S) "
text19: dc.b "                 "
text20: dc.b "            WRITTEN BY :            "
text21: dc.b "   R. GELFAND AND S. THUBEAUVILLE   "
       align.w
floppy:
 dc.l $00000000,$00000000,$00000000,$00000000,$000007ff,$ffffffe0
 dc.l $04000000,$002005ff,$ffffffa0,$05ffffff,$ffa00400,$00000020
 dc.l $04ffffff,$ff200880,$00000110,$08800000,$01100880,$1ff80110
 dc.l $08801008,$011008bf,$f00ffd10,$07a00000,$05e008bf,$f00ffd10
 dc.l $08800ff0,$01100a90,$00000110,$08800000,$01100480,$00000120
 dc.l $04ffffff,$ff200400,$00000020,$07ffffff,$ffe00000,$00000000
floppyend:
;graphic of disk drive not used by NTSC system

;Fast Copy

DecodeCnt:     dc.w 0      ;Counter for longwords to be decoded 
DecodeAdr:     dc.l 0      ;Address where to decode 
BlockAdr:      dc.w 0      ;Offset in Block for decoding 
FTestAdr:      dc.l 0      ;Test address if Block already loaded 
SectNum:       dc.w 0      ;Counter for Sector number
BytesBefGap:   dc.w 0      ;Bytes before the Gap
BytesAftGAp:   dc.w 0      ;Bytes after the Gap
FirstBlock:    dc.w 0      ;Block number of the first Block
FirstBlockSp:  dc.w 0      ;permanent memory for first Block
SectBL:        dc.w 0      ;Sector counter for Sectors before the Gap
VerifyFlag:    dc.w 0      ;indicates if read or Verify
VerErrFlag:    dc.w 0      ;Flag for Errors 
                           ;Verify-Bit = 1 => Error
TNumBufferA:   dc.w 0      ;Track-Number memory 
                           ;for 1D-Copy (Start-Track)
TNumBufferE    dc.w 0      ;Buffer for End number 
                           ;of loaded Tracks
BlockMessage:  ds.w 11

;Cruncher

Length:         dc.w $1600
ShrtByte:       dc.b 0
               align.w
TrackPointer:   ds.l 164   ;memory for Pointer to packed Tracks
MemoryBeg:      dc.l 0     ;memory beginning for crunching
MemoryLength:   dc.l 0     ;memory length for Crunching
MemoryChip:     dc.l 0
LengthChip:     dc.l 0
FreeFlagCh:     dc.w 0
MemoryFast:     dc.l 0
LenghtFast:     dc.l 0
FreeFlagFa:     dc.w 0
Subtr:          dc.w 0     ;See CrunEnd2

;Control 

TrackBuffer1:  dc.l 0
TrackBuffer2:  dc.l 0
TrackNumS:     dc.w 0
TrackNumD:     dc.w 0
TrackNum:      dc.w 0
StartTrack:    dc.w 0      ;first Track to be read
EndTrack       dc.w 0      ;last Track to be read
MotorBits:     dc.b $F3
MotorBitsS:    dc.b $F3
MotorBitsD:    dc.b $F3
Flag:          dc.b $00    ;indicates if Source or Dest.
               align.w

;Deep Copy

Position:      dc.l 0      ;For Search routine
BitShifts:     dc.w 0      ;number of Bits during shift
Size1:         dc.w 0      ;size of the largest Block
Size2:         dc.w 0      ;size of the second largest Block
SizePos:       dc.l 0      ;Position of the largest Block
Searchln:      dc.w 0      ;how many defective Words can there be
NumWords:      dc.w 0      ;how many Words are compared
ErrorFlag:     dc.w 0
EndPos:        dc.l 0      ;End position of Track
BegPos:        dc.l 0      ;beginning of Track (after Gap)
SLength:       dc.w 0      ;number of Bytes to be written
WriteAddrs:    dc.l 0      ;Address from which writing starts
Offset:        dc.w 0      ;number of Bytes before Sync during writing
TrackBytes:    dc.w 0      ;Bytes on the Track
CheckLength:   dc.w 0      ;Bytes on the Track (Controll)
LenghtDest:    dc.w 0      ;Track length of Dest.-Disk
Syncwidth:     dc.w 0      ;Distance from Index to Sync
SyncNum:       dc.w 0      ;number of Syncs found
CopyTry1:      dc.w 0      ;Illegal Data, read how many times
CopyTry2:      dc.w 0      ;how many times read for NoSync

Blocks:        ds.l SortBlockNum ;memory for Blocklength+SyncNum
SortBlocks:    ds.l SortBlockNum ;memory for Block sorting 
NumSortBlock:  dc.w 0      ;number of different sorted Blocks

SyncWord:      dc.w $4489  ;Value for reading

;Table for Sync-Search 
;Sync = $4489
SyncBase:      dc.l %01000100100010010000000000000000
               dc.l %00100010010001001000000000000000
               dc.l %00010001001000100100000000000000
               dc.l %00001000100100010010000000000000
               dc.l %00000100010010001001000000000000
               dc.l %00000010001001000100100000000000
               dc.l %00000001000100100010010000000000
               dc.l %00000000100010010001001000000000
               dc.l %00000000010001001000100100000000
               dc.l %00000000001000100100010010000000
               dc.l %00000000000100010010001001000000
               dc.l %00000000000010001001000100100000
               dc.l %00000000000001000100100010010000
               dc.l %00000000000000100010010001001000
               dc.l %00000000000000010001001000100100
               dc.l %00000000000000001000100100010010
               dc.l %00000000000000000100010010001001

AmigaTrack:    dc.b 0  ;indicates if Amiga-Format on DeepCopy

fc:  dc.b 00    ;First Cylinder
lc:  dc.b 79    ;Last    "
tr:  dc.b 3     ;Tries
ws:  dc.b 0     ;Write repeatedly 
vd:  dc.b 1     ;Verify
fa:  dc.b 1     ;Fast Copy
dc1: dc.b 0     ;D1 Copy
dc2: dc.b 0     ;D2 Copy
sd:  dc.b 1     ;SourceBits
dd:  dc.b 2     ;DestDits
sy:  dc.b 0     ;Sync correction 

waiting: dc.b 0 ;irq wait_conter

DevName:       dc.b "trackdisk.device",0

               END

