;----------------------------------------------------------
; DC v1.0:  Diskcopy, 1.4M disks only.   By Tenie Remmel.
; Note:  Link with VM, the virtual memory system.
;----------------------------------------------------------

Ideal

Extrn       VMproc:near

Model Tiny
CodeSeg
P386
Org 100h

Start:      jmp Main                ;Jump to main proc

;----------------------------------------------------------

Insert$1    db 'source$'
Insert$2    db 'target$'
Insert$X    db 13,10,'Insert $'
Insert$Y    db ' disk...$'
CRLF$       db 13,10,'$'

Again$      db 13,10,'Write another copy (Y/N)? $'

Reading$    db 13,'Read$'
Writing$    db 13,'Writ$'
Track$      db 'ing track '
TrackNum    db '??$'

ErrTrans    db 0,0,2,4,6,0,8,0,10,10,0,0,12,0,0,0,14,14

ErrTable    dw offset Error$0
            dw offset Error$1
            dw offset Error$2
            dw offset Error$3
            dw offset Error$4
            dw offset Error$5
            dw offset Error$6
            dw offset Error$7

Error$X     db 13,10,'Error: $'
Error$0     db 'Internal error$'
Error$1     db 'Bad sector$'
Error$2     db 'Disk is write protected$'
Error$3     db 'Sector not found$'
Error$4     db 'Drive not ready$'
Error$5     db 'DMA overrun$'
Error$6     db 'Invalid media$'
Error$7     db 'Read error$'

;----------------------------------------------------------

Main:       mov ax,2523h            ;Set null CtrlC handler
            mov dx,offset CtrlC
            int 21h

            mov ah,0                ;Init VM system
            call VMproc
            jc Error

            mov bp,offset Buffer    ;BP = buffer offset normalized
            mov dx,cs               ;to start on a 4K boundary, so
            shl dx,4                ;as to not cause DMA errors.
            add dx,bp
            neg dx
            and dx,0FFFh
            add bp,dx

            mov ah,9                ;Display insert message
            mov dx,offset Insert$X
            int 21h
            mov dx,offset Insert$1
            int 21h
            mov dx,offset Insert$Y
            int 21h

            xor ah,ah               ;Wait for a key
            int 16h

            mov ah,9                ;Move to next line
            mov dx,offset CRLF$
            int 21h

            call DCheck             ;Check for disk

            mov cx,1                ;Start with track 0
            mov dl,0                ;Drive A

;----------------------------------------------------------

ReadLoop:   mov bx,offset Reading$  ;Display track number
            call DispTrack

            mov bx,bp               ;BX = buffer
            mov dh,0                ;Head 0
            mov ax,0212h            ;Read 18 sectors
            int 13h
            jc Error
            add bx,2400h
            mov dh,1                ;Head 1
            mov ax,0212h            ;Read 18 sectors
            int 13h
            jc Error

            pusha                   ;Save all registers
            movzx ebx,ch            ;EBX = VM offset
            imul ebx,4800h
            mov cx,4800h            ;4800h bytes
            mov dx,bp               ;DX = buffer
            mov ah,3                ;Write to VM
            call VMproc
            mov ah,0
            jc Error
            popa                    ;Restore registers

            inc ch                  ;Next track
            cmp ch,80               ;Loop back
            jb ReadLoop

;----------------------------------------------------------

Write:      mov ah,9                ;Display insert message
            mov dx,offset Insert$X
            int 21h
            mov dx,offset Insert$2
            int 21h
            mov dx,offset Insert$Y
            int 21h

            xor ah,ah               ;Wait for a key
            int 16h

            mov ah,9                ;Move to next line
            mov dx,offset CRLF$
            int 21h

            call DCheck             ;Check for disk

            mov cx,1                ;Start with track 0
            mov dl,0                ;Drive A

;----------------------------------------------------------

WriteLoop:  mov bx,offset Writing$  ;Display track number
            call DispTrack

            pusha                   ;Save all registers
            movzx ebx,ch            ;EBX = VM offset
            imul ebx,4800h
            mov cx,4800h            ;4800h bytes
            mov dx,bp               ;DX = buffer
            mov ah,2                ;Read VM memory
            call VMproc
            mov ah,0
            jc Error
            popa                    ;Restore registers

            mov bx,bp               ;BX = buffer
            mov dh,0                ;Head 0
            mov ax,0312h            ;Write 18 sectors
            int 13h
            jc Error
            add bx,2400h
            mov dh,1                ;Head 1
            mov ax,0312h            ;Write 18 sectors
            int 13h
            jc Error

            inc ch                  ;Next track
            cmp ch,80               ;Loop back
            jb WriteLoop

            mov ah,9                ;Display question
            mov dx,offset Again$
            int 21h

            xor ah,ah               ;Wait for a key
            int 16h
            int 29h                 ;Display the key

            cmp al,'y'              ;If 'y' or 'Y', go again
            je Write
            cmp al,'Y'
            je Write

            mov ah,1                ;Close VM system
            call VMproc
            mov ax,4C00h            ;Exit to DOS
            int 21h

;----------------------------------------------------------

CtrlC:      clc                     ;Null CtrlC handler
            retf 2

;----------------------------------------------------------

DCheck:     mov ah,0                ;Reset disk 0
            mov dl,0
            int 13h
            jc Error

            mov bx,bp               ;Read first sector
            mov cx,1                ; to check for disk
            xor dx,dx
            mov ax,0201h
            int 13h
            mov ax,0201h
            int 13h
            jc Error
            ret

;----------------------------------------------------------

DispTrack:  pusha                   ;Save all registers

            mov cl,10               ;Convert track number
            mov al,ch
            xor ah,ah
            div cl
            add ax,3030h            ;Set track number
            mov [word TrackNum],ax

            mov ah,9                ;Display track number
            mov dx,bx
            int 21h
            mov dx,offset Track$
            int 21h

            popa                    ;Restore registers
            ret                     ;Return

;----------------------------------------------------------

Error:      shr ax,8                ;AL = error code
            cmp al,80h              ;80h --> 6
            jne $+4
            mov al,6
            cmp al,10h              ;Invalid error?
            jbe $+4
            xor al,al

            xchg bx,ax              ;BX = error code
            mov bl,[ErrTrans+bx]    ;BX = message ptr.
            mov bx,[ErrTable+bx]    ;BX = message
            mov ah,9                ;Print message
            mov dx,offset Error$X
            int 21h
            mov dx,bx
            int 21h

            mov ah,1                ;Close VM system
            call VMproc
            mov ax,4C01h            ;Exit with error
            int 21h

Buffer:

End Start
