home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
SIMTEL
/
CPMUG
/
CPMUG078.ARK
/
SDCOPY.ASM
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
10KB
|
360 lines
;SDCOPY.ASM
;V1.0
;*************************************************************
; THIS PROGRAM IS USED TO COPY A FILE FROM
; ONE DISKETTE TO ANOTHER ON A CP/M SYSTEM
; WHICH HAS ONLY ONE DISK DRIVE.
;
; IF FILE IS LARGER THAN AVAILABLE MEMORY IT IS
; COPIED IN MULTIPLE PASSES - EACH PASS READS
; AS MUCH AS WILL FIT IN MEMORY, WRITES IT OUT AFTER
; ASKING FOR DESTINATION DISK, THEN ASKS FOR SOURCE AGAIN.
;*************************************************************
;
;
; WARD'S BDOS/CBIOS EQUATES (VERSION 6)
;
RDCON EQU 1
WRCON EQU 2
PRINT EQU 9
RESETDK EQU 13
SELDK EQU 14
OPEN EQU 15
CLOSE EQU 16
SRCHF EQU 17
SRCHN EQU 18
ERASE EQU 19
READ EQU 20
WRITE EQU 21
MAKE EQU 22
RENAME EQU 23
STDMA EQU 26
BDOS EQU 5
FCB EQU 5CH
;
;******************************************
;
ORG 100H
;
;******************************************
; SAVE THE LOCAL STACK
;******************************************
LXI H,0
DAD SP
SHLD STACK
LXI SP,STACK
;******************************************
; CREATE DUPLICATE FCB FOR OUTPUT FILE
;******************************************
LXI D,FCB
LXI H,FCB2
MVI B,33
CALL MOVER
;
CALL ILPRT
DB 'SINGLE-DRIVE COPY 3/10/81',0DH,0AH,0
CALL OPNSRC
;
OPENOK: LXI D,BUFF ;POINT TO BUFFER
READLP: PUSH D ;SAVE BUFFER ADDRESS
; SET THE DMA ADDR
MVI C,STDMA
CALL BDOS
;
;******************************************
; READ A SECTOR
;******************************************
LXI D,FCB
MVI C,READ
CALL BDOS
;
ORA A ;OK?
JNZ EOF ;NOT OK, MUST BE EOF
LHLD FCT ;LOAD SECTOR COUNT FOR FILE
INX H ;BUMP BY 1
SHLD FCT ;SAVE IT BACK
POP D ;GET DMA ADDR
LXI H,80H
DAD D ;CALC NEXT BUFF ADDR
XCHG ;PUT IT BACK IN DE
;******************************************
; OUT OF MEMORY?
;******************************************
LDA 7 ;GET BDOS PAGE POINTER
SUI 0AH ;SUBTRACT OFFSET TO BELOW CCP
CMP D ;ABOUT TO HIT CCP?
JZ FULL ;YES - WRITE WHAT WE HAVE
JNC READLP ;NO, LOOP
;******************************************
;FILE IS TOO BIG - WRITE FIRST PART
;******************************************
FULL: JMP DESTMSG
;******************************************
;GOT RETURN CODE ON READ, SEE IF ERROR OR EOF
;******************************************
EOF: POP D ;POP BUFF ADDR OFF STACK
DCR A ;EOF?
JNZ RERROR ;NO, READ ERROR
XRA A ;SET DONE FLAG
STA DONEF ;SAVE FLAG FOR CHECKING LATER
JMP DESTMSG ;GO TO OUTPUT ROUTINE
;******************************************
;FILE READ INTO MEMORY. ASK FOR DEST. DISK
;******************************************
DESTMSG:CALL ILPRT
DB 'MOUNT DESTINATION DISK, TYPE D: ',0
;
; GET CHARACTER FROM CONSOLE
MVI C,RDCON
CALL BDOS
;
ANI 5FH ;MAKE IT UPPER CASE
CPI 'D' ;IS IT A D?
JZ RESET ;YES, RESET R/O STATUS
CPI 03H ;IS IT CTL-C
JZ DONE ;YES - REBOOT
JMP DESTMSG ;NO - GO ASK AGAIN
;******************************************
; RESET DISK TO DISABLE R/O STATUS
;******************************************
RESET: MVI C,RESETDK
CALL BDOS
;
CALL LOGIN
;
OUTOPN: LDA OPNOUT ;HAS OUTPUT FILE BEEN CREATED?
ORA A
JNZ CREATE ;NO-CREATE IT
;******************************************
; OPEN THE OUTPUT FILE
;******************************************
LXI D,FCB2 ;YES-JUST OPEN IT
MVI C,OPEN
CALL BDOS
;
INR A ;WAS OPEN OK?
JNZ WRTFIL ;YES-GO WRITE IT
CALL ILPRT ;LOOKS LIKE THE WRONG DISKETTE
DB 0DH,0AH,'** WRONG DISKETTE **',0DH,0AH,0
JMP DESTMSG ;GO ASK FOR OUTPUT DISK AGAIN
CREATE: XRA A ;SET FLAG
STA OPNOUT
STA FCB2+12 ;ZERO EXTENT #
STA FCB2+32 ;ZERO SECTOR #
;******************************************
; ERASE EXISTING FILE WITH SAME NAME (IF ANY)
;******************************************
LXI D,FCB2
MVI C,ERASE
CALL BDOS
;
;******************************************
; CREATE THE OUTPUT FILE
;******************************************
LXI D,FCB2
MVI C,MAKE
CALL BDOS
;
INR A
JZ BADMAKE ;MAYBE DIRECTORY IS FULL?
;******************************************
; WRITE THE FILE TO DISK
;******************************************
WRTFIL: LHLD FCT ;ANYTHING TO WRITE?
MOV A,H
ORA L
JZ CLOSEF ;NO - CLOSE OUTPUT FILE
LXI D,BUFF ;POINT TO BUFFER
WRLP: PUSH D ;SAVE THE DMA ADDR
MVI C,STDMA ;SET DMA ADDRESS
CALL BDOS
;******************************************
; WRITE THE SECTOR
;******************************************
LXI D,FCB2
MVI C,WRITE
CALL BDOS
;
ORA A ;WAS THE WRITE SUCCESSFUL?
JNZ WRERR ;NO, EXIT W/ERROR MSG
POP D ;GET DMA ADDR
LXI H,80H ;GET BUFFER LENGTH
DAD D ;CALC NEXT DISK WRITE ADDR
XCHG ;SAVE IN DE
LHLD FCT ;GET FILE'S SECTOR COUNT
DCX H ;DECREMENT IT
SHLD FCT ;SAVE IT BACK
MOV A,H ;IS IT ZERO?
ORA L
JNZ WRLP ;IF MORE, LOOP
;******************************************
; CLOSE THE FILE
;******************************************
CLOSEF: LXI D,FCB2
MVI C,CLOSE
CALL BDOS
;
LDA DONEF ;DONE ?
ORA A
JZ DONE ;YES - CLOSE FILE
LXI H,0 ;NO - CONTINUE
SHLD FCT
CALL OPNSRC
CALL LOGIN
JMP OPENOK
;******************************************
DONE EQU $ ;FILE HAS BEEN COPIED
;******************************************
; RESET DMA ADDR T0 80H
;******************************************
LXI D,80H
MVI C,STDMA
CALL BDOS
;
CALL MSGEXIT ;EXIT PRINTING FOLLOWING:
DB '++DONE++',0DH,0AH,'$'
;******************************************
; READ ERROR - EXIT WITH MSG
;******************************************
RERROR: CALL MSGEXIT
DB '++READ ERROR++$'
;******************************************
; GOT A WRITE ERROR - EXIT W/ERROR MSG.
;******************************************
WRERR: CALL MSGEXIT
DB '++WRITE ERROR++$'
;******************************************
; COULDN'T MAKE THE FILE, EXIT W/ERROR MSG.
;******************************************
BADMAKE:CALL MSGEXIT
DB '++CAN''T MAKE OUTPUT FILE$'
;******************************************
; INLINE PRINT ROUTINE - CALL ILPRT FOLLOWED
; BY MESSAGE (ENDING IN 0)
;******************************************
ILPRT: MVI A,0DH ;CR..
CALL TYPE
MVI A,0AH ;LF FIRST.
CALL TYPE
XTHL ;SAVE HL, GET MSG ADDR
ILPLP: MOV A,M ;GET CHAR OF MSG
PUSH H ;SAVE H
CALL TYPE ;TYPE CHAR
POP H ;GET H AGAIN
INX H ;POINT TO NEXT CHAR
MOV A,M ;GET IT
ORA A ;IS IT END OF MSG?
JNZ ILPLP ;NO, LOOP
INX H ;SKIP THE 0
XTHL ;RESTORE HL, STACK RET ADDR
RET ;..AND RETURN
;******************************************
; TYPE CHAR IN A
;******************************************
TYPE:
; WRITE TO CONSOLE
MOV E,A
MVI C,WRCON
CALL BDOS
;
RET
;******************************************
; CHAR MOVE ROUTINE, (DE) -> (HL) LEN IN B
;******************************************
MOVER: LDAX D ;GET SOURCE CHAR
MOV M,A ;STORE IN DEST. LOCATION
INX D ;POINT TO NEXT SOURCE
INX H ;POINT TO NEXT DEST.
DCR B ;DECREMENT COUNT
JNZ MOVER ;LOOP UNTIL ZERO
RET ;..THEN RETURN
;******************************************
; EXIT WITH ERROR MESSAGE
;******************************************
MSGEXIT:MVI A,0DH
CALL TYPE
MVI A,0AH
CALL TYPE
POP D ;GET MSG ADDRESS
; PRINT A MESSAGE
MVI C,PRINT
CALL BDOS
;******************************************
; EXIT, RESTORING STACK AND RETURN
;******************************************
EXIT: CALL ILPRT
DB 0DH,0AH,'RE-BOOTING '
DB 'VIA "JMP 0000", '
DB 'PRESS RETURN',0
; READ A CHARACTER
MVI C,RDCON
CALL BDOS
;
CPI 0DH
JNZ EXIT
LHLD STACK ;GET ORIGINAL STACK POINTER
SPHL ;AND RELOAD
JMP 0000H ;REBOOT CP/M
;******************************************
; REQUEST SOURCE DISKETTE + OPEN FILE
;******************************************
OPNSRC: CALL ILPRT
DB 'MOUNT SOURCE DISK, TYPE S: ',0
; GET THE CHARACTER
MVI C,RDCON
CALL BDOS
;
ANI 5FH ;MAKE UPPER CASE
CPI 'S'
JZ OPENIN ;YES - OPEN INPUT FILE
CPI 03H ;IS IT CTL-C?
JZ DONE ;YES - REBOOT
JMP OPNSRC ;NO - GO ASK AGAIN
;******************************************
;'S' WAS TYPED, OPEN THE INPUT FILE
;******************************************
OPENIN EQU $
; OPEN THE FILE
LXI D,FCB
MVI C,OPEN
CALL BDOS
;
INR A ;WAS THE OPEN OK?
RNZ ;YES - RETURN
;******************************************
; OPEN WAS BAD ON SOURCE DISKETTE
;******************************************
CALL ILPRT ;LOOKS LIKE THE WRONG DISKETTE
DB 0DH,0AH,'** WRONG DISKETTE **',0DH,0AH,0
JMP OPNSRC ;GO ASK FOR INPUT DISK AGAIN
;******************************************
; LOG IN THE MOUNTED DISK
;******************************************
LOGIN EQU $
LXI D,0
MVI C,SELDK
CALL BDOS
;
RET
;
;****************************************
; DATA AREA STARTS HERE
;****************************************
;
DONEF: DB 0FFH ;COPY DONE FLAG
OPNOUT: DB 0FFH ;OUTPUT OPEN FLAG
FCT: DW 0 ;FILE COUNT
;FOLLOWING FROM WARD'S "EQU5.LIB"---->
DS 40H ;STACK AREA
STACK: DS 2
;******************************************
; SECOND FCB (FOR OUTPUT FILE)
;******************************************
FCB2: DS 33
;******************************************
; BUFFER AREA STARTS RIGHT AFTER PROGRAM CODE
; AND DATA, AND EXTENDS TO JUST BELOW CCP
;******************************************
BUFF EQU $
END