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
/
CPM
/
UTILS
/
HDUTL
/
FLOPCOPY.ASM
< prev
next >
Wrap
Assembly Source File
|
2000-06-30
|
17KB
|
709 lines
; FLOPPY DISK COPY PROGRAM
; COPYRIGHT 1982, G. YOUNG, INC.
; UPDATED 10/9/82
*
* TO EXECUTE, ENTER THE PROGRAM NAME FOLLOWED BY THE FILE MASK:
* A>FLOPCOPY *.COM
*
* THE PRIMARY PURPOSE OF THIS PROGRAM IS TO COPY A FLOPPY DISK ON
* SYSTEMS THAT HAVE ONLY ONE FLOPPY DISK AND A HARD DISK. THIS IS DONE
* BY READING THE DIRECTORY ON THE FLOPPY AND CREATING A LIST OF FILES TO
* TO BE COPIED, THEN COPY ALL THE FILES TO THE HARD DISK. A BLANK
* DISK IS THEN INSERTED AND THE FILES ARE COPIED TO THE BLANK FLOPPY
* AND DELETED OFF THE HARD DISK. THIS PROCEDURE IS USED INSTEAD OF
* THE "SINGLE.COM" PROGRAM BECAUSE THERE IS MORE THAN 1 FILE SO "SINGLE"
* CANNOT BE USED WITHOUT MODIFICATIONS AND EVEN THEN MANY, MANY DISKETTE
* MOUNTS WOULD HAVE TO BE DONE. THIS WAY, ONLY 1 DISKETTE MOUNT NEEDS
* TO BE DONE FOR EACH DISK THAT IS COPIED.
* 8/26/82...IF DISKETTE IS FULL, ASK FOR ANOTHER, DO NOT ABORT
* THIS ALLOWS COPYING DOUBLE DENSITY DISKS ON TO MULTIPLE SINGLE DENSITY DISKS
* 10/9/82 ASK FOR SOURCE/DESTINATION/HARD DISK DRIVE # AND NOT HARD CODED
* WRITTEN BY GARY YOUNG, BOX 3218, NO. HOLLYWOOD, CA 91609
TITLE '*** FLOPPY DISK COPY PROGRAM ***'
BDOS EQU 5
RECSIZE EQU 12
BOOT EQU 0
ORG 100H
JMP START
DB 'COPYRIGHT 1982, G. YOUNG, INC.'
START LXI SP,STACK+80
LDA 5DH ;SEE IF A MASK WAS ENTERED
CPI 20H ;BUFFER WILL BE BLANK IF NOT
JZ NOMASK
MVI C,0DH ;DISK RESET
CALL BDOS
LXI H,RAM ;SET UP TABLE ADDRESS
SHLD TABADDR
LXI H,0000H
SHLD TABCNT
XRA A ;THE TABLE REFERS TO THE REMAINING AREA
STA ABORT ;OF RAM TO HOLD AS MANY DIRECTORY ENTRIES
STA EOF ;AS POSSIBLE
LXI D,SIGNON ;PRINT SIGNON MESSAGE
CALL OUTPUT
LXI D,SRCFLPMSG ;GET SOURCE DRIVE
CALL QUESTION
ORA A
JZ QUEST2
LDA INREC
STA SRCFLP
QUEST2 LXI D,DESTFLPMSG
CALL QUESTION
ORA A
JZ QUEST3
LDA INREC
STA SRCFLP
QUEST3 LXI D,HDMSG
CALL QUESTION
ORA A
JZ QUEST4
LDA INREC
STA HDTEMP
QUEST4 LDA HDTEMP
ANI 0FH
STA HDTEMP
LDA SRCFLP
ANI 0FH
STA SRCFLP
LDA DESTFLP
ANI 0FH
STA DESTFLP
CALL EXTRACT ;GET DIRECTORY ENTRIES
LDA ABORT ;SEE IF TOO MANY ENTRIES FOR MEMORY SIZE
ORA A ;SHOULD BE ZERO TO BE OK
JZ NOMORE
LXI D,TABFULL ;REPORT WILL NOT BE COMPLETE
CALL OUTPUT ;MEMORY FULL ERROR
NOMORE CALL SORT
CALL KILLDUPS ;REMOVE ENTRIES FROM MULTIPLE EXTENTS
LDA SRCFLP ;FLOPPY IS THE SOURCE DRIVE
STA SRCE
LDA HDTEMP ;HARD DISK IS THE DESTINATION
STA DEST
CALL CPYFILE
AGAIN LXI D,MNTBLANK
CALL QUESTION
MVI C,0DH
CALL BDOS
LDA HDTEMP
STA SRCE
LDA DESTFLP
STA DEST
CALL CPYFILE
MSG3 LXI D,ANOTHER
CALL QUESTION
ORA A
JZ WIPEOUT
LDA INREC
CPI 'N'
JZ WIPEOUT
CPI 'Y'
JNZ MSG3
JMP AGAIN
WIPEOUT CALL ERASE
JMP BOOT ;RESET AND RETURN TO CPM
NOMASK LXI D,ERRNOMSK
CALL OUTPUT
JMP BOOT
*
* THE EXTRACT ROUTINE SCANS THE DIRECTORY ON THE FLOPPY DISK
* AND CREATES A LIST OF FILES TO BE COPIED. AFTERS SORTING,
* DUPLICATE ENTRIES RESULTING FROM MULTIPLE EXTENT ENTRIES WILL
* BE REMOVED.
*
* THE DUMMYFCB SETS UP A SKELETON TO READ ALL FILES ON THE DIRECTORY
* TO BE MODIFIED BY THE SKELATON SETUP IN THE CALL (EX: FLOPCOPY *.ASC).
*
DUMMYFCB DB 0,'????????????',0,0,0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
EXTRACT EQU $
LXI D,DUMMYFCB ;COPY THE MASK SET UP BY CCP
LXI H,5CH ;OVER THE DUMMY FCB TO LIMIT WHAT IS COPIED
MVI B,12
CALL MOVE
LDA SRCFLP ;FORCE THE DRIVE TO BE FLOPPY DRIVE
STA DUMMYFCB
ORI 40H
STA RDISK
LXI D,DISKBUF ;SET A DMA ADDRESS FOR DIRECTORY ENTRIES
MVI C,1AH
CALL BDOS ;SET DMA
LXI D,DUMMYFCB ;GET FIRST DIRECTORY ENTRY
MVI C,11H
CALL BDOS ;GET DIRECTORY
INR A
RZ
JMP GETFCB ;EXTRACT DATA FROM FCB
NEXTFCB LXI D,DUMMYFCB ;GET NEXT ENTRY AFTER THE FIRST
MVI C,12H
CALL BDOS
INR A
RZ
GETFCB LXI D,32 ;EACH ENTRY IS 32 BYTES LONG
LXI H,DISKBUF ;DIRECTORY RECORD IS IN DISKBUF
CPI 1 ;FIRST ENTRY IN RECORD???
JZ FORMREC ;YES
DAD D ;ADD 32 TO ADDRESS IN RECORD
CPI 2 ;SECOND ENTRY IN RECORD???
JZ FORMREC
DAD D ;ADD 64 TO ADDRESS OF RECORD
CPI 3 ;THIRD ENTRY IN RECORD???
JZ FORMREC
DAD D ;ADD 96 TO ADDRESS OF RECORD
FORMREC INX H ;PASS DRIVE BYTE
LXI D,RFILE ;MOVE FILE NAME
MVI B,8 ;MOVE 8 CHARACTERS
CALL MOVE
LXI D,8 ;POSITION PAST NAME TO TYPE
DAD D
LXI D,RTYPE ;MOVE TYPE
MVI B,3 ;MOVE 3 CHARACTERS
CALL MOVE
INX H ;POSITION TO THE EXTENT NUMBER
INX H
INX H
LXI H,RTYPE ;STRIP OFF THE HIGH BIT SET BY
MVI B,11 ;THE VERSION PROGRAM
STRIP MOV A,M
ANI 07FH
MOV M,A
INX H
DCR B
JNZ STRIP
LXI H,RTYPE ;SKIP OVER JUNK DISK ENTRIES
MVI B,11 ;CONTAINING NONPRINTING CHARACTERS
NONPRNT MOV A,M
CPI 20H ;ANY CHAR LESS THAN A BLANK
JC NEXTFCB ;GO TO NEXT ONE IF SO
INX H
DCR B
JNZ NONPRNT
FIRSTEXT EQU $ ;GOT THE FIRST EXTENT
LHLD TABADDR ;GET MEMORY TABLE ADDRESS
LXI D,RTYPE ;GET MEMORY RECORD ADDRESS
XCHG ;RTYPE (HL) TO TABADDR (DE)
MVI B,RECSIZE ;MOVE RECSIZE BYTES
CALL MOVE
LHLD TABADDR ;INCREMENT FOR NEXT ENTRY
LXI D,RECSIZE ;RECSIZE BYTES IN RECORD
DAD D
SHLD TABADDR ;SAVE NEW ADDRESS
MVI M,1AH ;SET AN END-OF-TABLE INDICATOR
LHLD TABCNT ;GET RECORD COUNT
INX H
SHLD TABCNT ;INCREMENT RECORD COUNT
LHLD TABADDR ;SEE IF NEW ADDRESS IS GREATER
XCHG ;THAN THE TOP OF TPA-128
LHLD BDOS+1 ;HL=TOP...DE=TABLE+RECSIZE
LXI B,-128
DAD B ;SUBTRACT 128 FROM TOP
CALL COMPREG ;COMPARE REGISTER VALUES
JNC NEXTFCB ;THERE IS ROOM FOR MORE
MVI A,1 ;NO MORE ROOM...ABORT NOW
STA ABORT
RET
* COPY THE FILE FROM ONE DISK TO ANOTHER
* THIS CODE WAS TAKEN FROM BACKUP.ASM SO HDFCB REFERS TO THE SOURCE DISK
* AND FPFCB REFERS TO THE DESTINATION DISK REGARDLESS OF FLOPPY OR HARD.
CPYFILE EQU $
LHLD ADDR2 ;GET THE CURRENT END OF TABLE
INX H ;PLUS ONE FOR THE START OF THE
SHLD ADDR3 ;READ/WRITE BUFFER
LXI H,RAM ;SET THE ADDRESS OF THE FIRST ENTRY
SHLD ADDR1
JMP PASSMOVE
NEXTFILE EQU $
LHLD ADDR1
LXI D,RECSIZE
DAD D
SHLD ADDR1
PASSMOVE LHLD ADDR1
MOV A,M
CPI 1AH
RZ
FORMFCB LXI D,HDFCB ;CLEAR THE FCB
MVI B,36
XRA A
ZEROFCB STAX D
INX D
DCR B
JNZ ZEROFCB
LHLD ADDR1 ;GET ADDRESS OF TABLE ENTRY
LXI D,HDTYPE ;MOVE IN THE TYPE
MVI B,3
CALL MOVE
INX H
INX H ;POSITION TO NAME
INX H
LXI D,HDFILE ;MOVE THE FILE NAME
MVI B,8
CALL MOVE
LXI D,8
DAD D ;POSITION TO DISK ID, A:, B: ETC
LDA SRCE
STA HDFCB
LXI D,FPFCB ;COPY THE HDFCB TO THE FLOPPY FCB
LXI H,HDFCB
MVI B,36
CALL MOVE
LDA DEST
STA FPFCB
LHLD ADDR1
CALL FORMAT
LXI D,PRNTREC
CALL OUTPUT
LXI D,HDFCB ;OPEN THE SOURCE FILE DRIVE
MVI C,0FH
CALL BDOS
INR A
JZ NOTFOUND
LXI D,FPFCB ;SEE IF THE FILE IS ON THE DESTINATION DRV
MVI C,0FH
CALL BDOS ;DUMMY OPEN
INR A
JZ MAKEIT ;NOT THERE...MAKE IT
LHLD ADDR1 ;SET THE DRIVE BYTE (#12) TO '*' TO MARK
LXI D,RECSIZE-1 ;THE FILE AS ALREADY BEING THERE SO THAT
DAD D ;THE ERASE ROUTINE WILL NOT ERASE IT
MVI A,'*' ;LATER WHEN REMOVING FILES
MOV M,A
HUH2 LXI D,ALRDYEXT ;FILE ALREADY EXISTS ON DESTINATION. ASK IF
CALL QUESTION ;YOU WANT TO COPY THE NEW SOURCE OVER THE
CPI 1 ;EXISTING COPY
JNZ HUH2
LDA INREC
CPI 'Y'
JZ ERAIT ;ERASE IT
CPI 'N' ;NO, USE THE COPY ALREADY ON THE DESTINATION
JZ NEXTFILE
JMP HUH2
ERAIT EQU $
LXI D,FPFCB ;DELETE THE FILE ON FLOPPY IF IT
MVI C,13H ;EXISTS
CALL BDOS
MAKEIT EQU $
LXI D,FPFCB ;CREATE THE FILE ON FLOPPY
MVI C,16H
CALL BDOS ;MAKE FILE
INR A
JZ DISKFULL
COPYLOOP CALL LOADBUFF ;LOAD MEMORY WITH FILE
CALL WRITEBUF ;WRITE MEMORY FILE
LDA EOF
CPI 1
JZ ENDOFFILE
CPI 2
JZ DISKFULL
JMP COPYLOOP
ENDOFFILE LXI D,FPFCB ;CLOSE FLOPPY FILE
MVI C,10H
CALL BDOS ;CLOSE
JMP NEXTFILE
DISKFULL LXI D,FPFCB
MVI C,13H ;DELETE FILE ON FLOPPY
CALL BDOS
LXI D,DSKFULL ;PRINT DISK FULL MESSAGE
CALL QUESTION
MVI C,0DH ;RESET DISKS
CALL BDOS
JMP FORMFCB
NOTFOUND LHLD ADDR1
CALL FORMAT
LXI D,NFMSG
CALL OUTPUT
LXI D,PRNTREC
CALL OUTPUT
RET
ERASE EQU $
HUH LXI D,ERAMSG ;ASK IF YOU WANT THEM ERASED
CALL QUESTION
ORA A
JZ ERAALL
LDA INREC
CPI 'Y'
JZ ERAALL
CPI 'N'
RZ
JMP HUH
ERAALL EQU $
LXI H,RAM ;SET THE ADDRESS OF THE FIRST ENTRY
SHLD ADDR1
JMP PASSMOVEX
ERANEXT EQU $
LHLD ADDR1
LXI D,RECSIZE
DAD D
SHLD ADDR1
PASSMOVEX LHLD ADDR1
MOV A,M
CPI 1AH
RZ
LXI D,RECSIZE-1 ;SEE IF THE DRIVE INDICATOR IS SET TO '*'
DAD D ;MEANING THE FILE WAS ALREADY ON THE HARD DISK
MOV A,M ;SO IT WILL NOT BE DELETED
CPI '*'
JZ ERANEXT ;YES, IT WAS THERE, SO DO NOT ERASE IT
FORMFCBX LXI D,HDFCB ;CLEAR THE FCB
MVI B,36
XRA A
ZEROFCBX STAX D
INX D
DCR B
JNZ ZEROFCBX
LHLD ADDR1
LXI D,HDTYPE ;MOVE IN THE TYPE
MVI B,3
CALL MOVE
INX H
INX H ;POSITION TO NAME
INX H
LXI D,HDFILE ;MOVE THE FILE NAME
MVI B,8
CALL MOVE
LXI D,8
DAD D ;POSITION TO DISK ID, A:, B: ETC
LDA HDTEMP
STA HDFCB
LHLD ADDR1
CALL FORMAT
LXI D,PRNTREC
CALL OUTPUT
LXI D,HDFCB ;DELETE THE FILE ON FLOPPY IF IT
MVI C,13H ;EXISTS
CALL BDOS
JMP ERANEXT
* THE FOLLOWING ROUTINE IS A BUBBLE SORT. IN PSEUDOBASIC
* IS WOULD BE DONE AS FOLLOWS:
*SORT ADDR1=BOTTOM(RAM)-RECSIZE (RECSIZE IS COUNT OF BYTES IN ONE RECORD)
* MAX1=0
*LOOP1 MAX1=MAX1+1
* ADDR1=ADDR1+RECSIZE (FIRST TIME THIS WOULD BE THE BOTTOM)
* IF MAX1>TABCNT-1 THEN GO TO SORTED
* ADDR2=ADDR1
* MAX2=MAX1
*LOOP2 MAX2=MAX2+1
* ADDR2=ADDR2+RECSIZE
* IF MAX2>TABCNT THEN GO TO LOOP1
* IF TABLE(ADDR1)<TABLE(ADDR2) THEN GO TO LOOP2
* TEMP=TABLE(ADDR1)
* TABLE(ADDR1)=TABLE(ADDR2)
* TABLE(ADDR2)=TEMP
* GO TO LOOP2
*SORTED RETURN
*
*NOW THAT THIS LOGIC IS INTUITIVELY OBVIOUS, HERE'S THE NOT SO
*OBVIOUS CODE:
SORT
LXI H,0000 ;INITIALIZE COUNT
SHLD MAX1 ;SINCE IT WILL DECREMENT FIRST
LXI D,-RECSIZE ;SUBTRACT RECSIZE FROM THE BEGINNING
LXI H,RAM ;OF THE TABLE SINCE IT WILL ADD
DAD D ;RECSIZE TO IT FIRST
SHLD ADDR1
LOOP1 LHLD ADDR1 ;GET THE CURRENT ADDRESS
LXI D,RECSIZE ;INCREMENT IT BY RECSIZE
DAD D ;PAST THE NEXT ENTRY
SHLD ADDR1
LHLD MAX1 ;SEE IF THE COUNT HAS REACHED THE LIMIT
INX H ;INCREMENT THE COUNTER
SHLD MAX1
XCHG ;MOVE TO DE TO COMPARE TO LIMIT
LHLD TABCNT
DCX H ; IS MAX1 > TABCNT - 1 ???
CALL COMPREG ;COMPARE DE (CURRENT COUNT) TO HL (TABCNT-1)
JC SORTED ;FINISHED WHEN MAX1 > TABCNT-1
LHLD ADDR1 ;SETUP FOR THE INNER LOOP
SHLD ADDR2
LHLD MAX1
SHLD MAX2
LOOP2 LHLD ADDR2 ;START WITH ONE ENTRY GREATER THEN
LXI D,RECSIZE ;THE OUTER LOOP AND INCREMENT
DAD D ;BY RECSIZE EACH TIME PAST THE NEXT RECORD
SHLD ADDR2 ;POINTER TO THE CURRENT RECORD
LHLD MAX2 ;LIKEWISE SEE IF THE COUNTER FOR THE
INX H
SHLD MAX2
XCHG
LHLD TABCNT
CALL COMPREG
JC LOOP1 ;WHEN FINISHED, INCREMENT OUTER LOOP
LHLD ADDR2
XCHG ;ADDR2 NOW IN DE
LHLD ADDR1
CALL COMPARE ;COMPARE STRINGS POINTED TO BY DE/HL
JNC LOOP2 ;TABLE(HL) < TABLE (DE)
* EXCHANGE THE TWO ENTRIES VIA A TEMPORARY RECORD
LXI D,TEMP
LHLD ADDR1
MVI B,RECSIZE
CALL MOVE ;TEMP=TABLE(ADDR1)
XCHG ;ADDR1=DESTINATION
LHLD ADDR2 ;ADDR2=SOURCE
CALL MOVE ;TABLE(ADDR1)=TABLE(ADDR2)
XCHG ;ADDR2 = DESTINATION
LXI H,TEMP
CALL MOVE ;TABLE(ADDR2)=TEMP
JMP LOOP2
SORTED RET ;FINISHED SORTING
KILLDUPS EQU $ ;KILL DUPLICATE ENTRIES FROM MULTIPLE EXTENTS
LXI H,RAM
SHLD ADDR1 ;SET THE START OF THE TABLE
NEXTEQUAL LHLD ADDR1 ;CHECK EACH ENTRY AGAINST THE NEXT
LXI D,RECSIZE
DAD D
SHLD ADDR2
NEXTCHK MOV A,M ;CHECK FOR END OF TABLE
CPI 1AH
RZ
XCHG
LHLD ADDR1 ;COMPARE ADDR1 WITH ADDR2
MVI B,RECSIZE
CALL COMPARE
JNZ SAVELAST
PUSH H ;SAVE CURRENT POSITION
LHLD ADDR2 ;SET UP FOR MOVING LIST
SHLD ADDR1 ;DOWN ONE ENTRY
LXI D,RECSIZE
DAD D ;MOVE THIRD ENTRY TO THE SECOND
SHLD ADDR2
CALL MOVELIST
LHLD TABCNT
DCX H
SHLD TABCNT
POP H ;RESTORE CURRENT POSITION
SHLD ADDR1 ;NOW COMPARE 1ST & 3RD
JMP NEXTEQUAL
SAVELAST LHLD ADDR2 ;MAKE NEW ONE THE CURRENT ONE
SHLD ADDR1
JMP NEXTEQUAL ;COMPARE
MOVELIST LHLD ADDR2 ;MOVE THE TABLE FROM ADDR2 DOWN
XCHG ;TO ADDR1 THEREBY ELIMINATING
LHLD ADDR1 ;UNWANTED ENTRIES
MOVENEXT LDAX D ;AND MAKING MORE ROOM FOR THE
MOV M,A
CPI 1AH
RZ
INX H
INX D
JMP MOVENEXT
* ASSORTED ROUTINES
LOADBUFF EQU $ ;THIS ROUTINE LOADS AS MUCH OF
LXI H,0000 ;MEMORY WITH THE FILE AS POSSIBLE
SHLD MAX1
LHLD ADDR3 ;NEW TOP OF TABLE +2
SHLD TEMP
XRA A
STA EOF ;CLEAR EOF FLAG
LOADNEXT LHLD TEMP
XCHG ;SET DMA ADDRESS
MVI C,1AH
CALL BDOS
LXI D,HDFCB ;READ HARD DISK
MVI C,14H
CALL BDOS
ORA A
JNZ HDEOF ;EOF?
LHLD MAX1
INX H ;INCREMENT RECORD COUNT
SHLD MAX1
LHLD TEMP ;SEE IF NEXT RECORD WOULD EXCEED THE
LXI D,128 ;TPA AREA
DAD D
SHLD TEMP
DAD D ;WILL THE NEXT RECORD OVERWRITE BDOS?
XCHG
LHLD BDOS+1 ;FIND THE TOP OF MEMORY
CALL COMPREG ;COMPARE REGISTERS
RC ;RETURN IF MEMORY ALREADY FULL
JMP LOADNEXT ;GET ANOTHER RECORD
HDEOF MVI A,1 ;SET FILE EOF
STA EOF
RET
WRITEBUF EQU $ ;WRITE FROM THE MEMORY BUFFER
LHLD ADDR3
SHLD TEMP
LHLD MAX1 ;ALLOW FOR FILES THAT HAVE NO
LXI D,0000 ;RECORDS SUCH AS RESTART
CALL COMPREG
RZ
WRITENEXT LHLD TEMP
XCHG ;SET DMA ADDRESS
MVI C,1AH
CALL BDOS
LXI D,FPFCB
MVI C,15H ;WRITE SEQUENTIAL
CALL BDOS
ORA A
JNZ FPFULL ;FLOPPY DISK FULL
LHLD MAX1 ;DECREASE RECORD COUNT
DCX H
SHLD MAX1
LXI D,0000 ;CHECK FOR NO MORE TO WRITE
CALL COMPREG
RZ
LHLD TEMP
LXI D,128 ;INCREMENT WRITE ADDRESS
DAD D
SHLD TEMP
JMP WRITENEXT
FPFULL MVI A,2 ;FULL DISKETTE
STA EOF
RET
FORMAT LXI D,PRNTYPE ;FORMAT THE ENTRY FROM THE TABLE
MVI B,3 ;FORMAT TO THE PRINT FORMAT
CALL MOVE ;THE TABLE ADDRESS IS ASSUMMED TO BE
LXI D,3 ;IN HL. FIRST MOVE THE TYPE
DAD D ;NOW POSITION TO THE FILE NAME
LXI D,PRNFILE ;MOVE THE FILE NAME
MVI B,8
CALL MOVE
LXI D,8 ;POSITION TO THE DISK ID
DAD D
LDA SRCE
ORI 40H
STA PRNTREC
MVI A,':'
STA PRNTREC+1
MVI A,'.'
STA PRNTYPE-1
RET
COMPREG MOV A,H ;COMPARE HL TO DE
CMP D
RNZ
MOV A,L
CMP E
RET
OUTPUT PUSH D ;PUT OUT A CRLF
LXI D,CRLF
MVI C,09
CALL BDOS
POP D ;NOW PUT OUT THE MESSAGE
OUT1 MVI C,09
JMP BDOS
QUESTION CALL OUTPUT ;PUT OUT THE QUESTION
LXI D,INBUF
MVI C,0AH ;INPUT THE REPLY
CALL BDOS
LDA INCNT ;SEE IF ANYTHING WAS ENTERED
RET
MOVE PUSH H ;MOVE DATA POINTED TO IN HL
PUSH D ;TO THE AREA POINTED TO IN DE
PUSH B ;BY THE BYTE COUNT IN B
MOVE1 MOV A,M
ANI 7FH ;RESET THE HIGH ORDER BIT BECAUSE IT
;MAY HAVE BEEN TURNED ON FOR THE TYPE
STAX D
INX H
INX D
DCR B
JNZ MOVE1
POP B ;RESTORE THE TOTAL ENVIRONMENT
POP D
POP H
RET
COMPARE PUSH H ;COMPARE THE STRINGS POINTED TO IN HL
PUSH D ;TO THE STRING POINTED TO IN DE
PUSH B ;FOR A LENGTH OF B CHARACTERS
COMP1 LDAX D ; JC IF HL > DE
CMP M ; JZ IF HL = DE
JNZ COMP2 ;JNC IF HL < DE
INX H
INX D
DCR B
JNZ COMP1
COMP2 POP B
POP D
POP H
RET
SIGNON DB 'FLOPPY DISK COPY PROGRAM '
DB '10/9/82$'
ERRNOMSK DB 'ERROR...NO FILE MASK IN COMMAND'
DB CR,LF,'COMMAND MUST BE IN THE FORMAT "FLOPCOPY *.*"'
DB CR,LF,'$'
TABFULL DB 'MEMORY FULL...REPORT NOT COMPLETE$'
NFMSG DB 'FILE NOT FOUND...ABORTING$'
DMNTMSG DB 'DISMOUNT DISKETTE AND ENTER RETURN$'
ERAMSG DB 'ERASE COPIES ON THE HARD DISK (Y/N)? $'
MNTBLANK DB 'MOUNT A FORMATTED BLANK DISKETTE AND ENTER RETURN$'
ANOTHER DB 'WANT TO COPY THE SAME FILES ON TO ANOTHER DISKETTE (Y/N)? $'
ALRDYEXT DB 'FILE ALREADY EXISTS ON DESTINATION DISK.'
DB ' ENTER Y TO COPY OVER IT: $'
DSKFULL DB 'DISKETTE FULL...MOUNT ANOTHER DISK$'
PRNTREC DS 1
DB ':'
PRNFILE DS 8
DB '.'
PRNTYPE DS 3
DB ' $'
CRLFLFLF DB 0DH,0AH,0AH,0AH,'$'
CRLF DB 0DH,0AH,'$'
BIGMSG DB 0DH,0AH,'FILE TOO LARGE TO FIT ON ONE DISKETTE '
DB 'SO NOT BACKED UP **** $'
SRCFLPMSG DB 'SOURCE FLOPPY DRIVE (DEFAULT='
SRCFLP DB 'D) $'
DESTFLPMSG DB 'DESTINATION FLOPPY DRIVE (DEFAULT='
DESTFLP DB 'D) $'
HDMSG DB 'HARD DISK DRIVE USED AS BUFFER (DEFAULT='
HDTEMP DB 'A) $'
HDFCB DS 1
HDFILE DS 8
HDTYPE DS 3
DS 24
FPFCB DS 36
SRCE DS 1
DEST DS 1
INBUF DB 30
INCNT DS 1
INREC DS 30
STACK DS 80
EOF DS 1
ABORT DS 1
LINECNT DS 1
LASTTYPE DS 3
LASTFILE DS 8
TABADDR DS 2
TABCNT DS 2
SELFLAG DS 1
TOOBIG DS 1
ADDR1 DS 2
ADDR2 DS 2
ADDR3 DS 2
MAX1 DS 2
MAX2 DS 2
RTYPE DS 3
RFILE DS 8
RDISK DS 3
DB '$'
TEMP DS RECSIZE
DISKBUF DS 128
COMPSIZE DS 1
CR EQU 0DH
LF EQU 0AH
RAM EQU $
END 100H