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
/
BAKUP23A.LBR
/
BAKUP23A.AQM
/
BAKUP23A.ASM
Wrap
Assembly Source File
|
2000-06-30
|
34KB
|
1,306 lines
; DISK DIRECTORY AND BACKUP PROGRAM
; COPYRIGHT 1980, G. YOUNG, INC.'
; UPDATED 6/23/83
; updated again by W. F. Dudley N4BYT - 6/3/84 - marked by ### in comment
;
* THE PRIMARY PURPOSE OF THIS PROGRAM IS TO BACKUP HARD DISKS ON TO
* MULTIPLE FLOPPIES. FIRST, IT EXTRACTS THE DIRECTORIES FROM ALL OF
* THE HARD DISKS, SORTS BY TYPE AND FILE NAME, AND PRINTS A CONSOLIDATED
* DIRECTORY. THEN IT DELETES DUPLICATE FILES FROM THE CONSOLIDATED
* DIRECTORY, DELETES UNWANTED TYPES (PRN, BAK, ETC), AND UNWANTED
* FILES TO CREATE A LIST OF FILES TO BACKUP. THESE ARE COPIED TO
* MULTIPLE FLOPPIES AS NEEDED WHILE PRODUCING AN INDEX OF WHAT FILES ARE
* ON EACH DISKETTE. RESTART CAPABILITY IS PROVIDED TO BEGIN THE BACKUP
* AT ANY FILE.
* WRITTEN BY GARY YOUNG, BOX 3218, NO. HOLLYWOOD, CA 91609
* CORRECTIONS BY RON STEVENSON, 35 E. GAULT WAY, SPARKS, NV. 89431
* Corrections by W. F. Dudley Jr., N4BYT, uucpnet hou2g!dud
; 06/03/84 wfd v2.3a
; added to routine QUESTION so that lower case responses are converted
; to upper case.
; changed routine REPORT and TOPOFFORM so that a <cr> is sent to the
; printer before formfeeds. This is because some printers (like my
; Base 2) won't print the line buffer until a <cr> is rec'd, but will
; do a formfeed any old time.
; added the DIAGNST equate to switch on or off the diagnostic display
; without having to remove or add comment semicolons.
; What this sucker really needs is the ability to scan across all 16 user
; areas, and write all of the files it finds in the different areas
; out to the floppys, preserving user numbers and other attributes.
; I'd do it, but it is not obvious to me how the file name data structure is
; kept in the ram buffer. Is it just a bunch of FCB copies?
; 08/22/83 rds v2.3
; Added the following options. First is for a printed report of all
; files to be backup is now turn on or off by answering the question
; of 'Do you wish a Printed Report (Y/N)' at the start. Move the
; verify inputed data question to after the input of date to verify
; this as well. Last is an add at end of program to ask if you wish
; to run this program again in case you have two areas with same file
; names but different data like a personal and buisness GL. This is
; only needed if you have a disk that's divided into two or more
; logical drives/volumes like the Molecular.
; 07/01/83 rds v2.2
; Added features to mark files that have been backed up on the floppy
; bye eather setting the 'T3' byte of the FCB for Molecular computers
; or setting the 'F4' byte for other computers. This is done at asm.
; time bye setting the MOLEC equate for eather.
; 06/23/83 rds v2.1
; Corrected problem in code for backing up to copying to drive 'P'.
; original code stripe off too many bits which wouldn't allow program
; to see drive 'P' no matter what. Also clean up some of the code.
; 06/13/83 rds v2.0
; Added code at begining for setting up the drive to backup from as
; well as too. You are now prompted as to which drives you want backup
; and then which drive to put the stuff on..
;
TITLE '*** HARD DISK BACKUP PROGRAM ***'
ORG 100H
JMP START
DB 'COPYRIGHT 1980, G. YOUNG, INC.'
;
FALSE EQU 0
TRUE EQU NOT FALSE
;
MOLEC EQU false ;TRUE FOR MOLECULAR and FALSE FOR OTHERS
diagnst equ false
;
RECSIZE EQU 12 ;RECORD SIZE AS FOLLOWS
; TYPE = 3 BYTES
; FILE = 8 BYTES
; DISKID = 1 BYTES
NOSKIP EQU 6 ;NUMBER OF FILES IN SKIP LIST
SKIPTYPE DB 'PRNHEXSYMBAK$$$TMP' ;FILES TO NOT BACK UP
IDSIZE EQU 1 ;ID NOW MEANS A:, B:, C:, ETC
LINESPAGE EQU 60 ;LINES PER PAGE
RECLINE EQU 4 ;ENTRIES PER LINE
;
;
START LXI SP,STACK+80
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
STA PRNTFLG ;TURN ON PRINTER FLAG 0 = PRINT
START1: LXI D,SIGNON ;PRINT SIGNON MESSAGE
CALL OUTPUT
LXI D,DRIVMSG ;ASK FOR THE DRIVE LETTERS TO BACKUP
CALL QUESTION
CPI 0 ;CK TO SEE IF ANYTHING WAS ADDED
JZ START1 ;IF NOT START OVER
ADI 1
STA MAX1
MOV B,A ;SETUP COUNT FOR MOVE
LXI H,INREC ;DATA TO MOVE
LXI D,DRIVES ;WHERE TO PUT THE DATE
CALL MOVE
XCHG
DCR B ;CORRECT THE COUNT BEFOR CKING
STRT: MOV A,M ;GET A DRIVE CHAR
CPI 'Q' ;CK IT FOR GOOD CHAR
JP START1 ;NO GOOD IF POSITIVE
INX H ;POINT TO NEXT
DCR B ;DEC COUNT
JNZ STRT ;LOOP
MVI M,'$' ;STORE END-OF-STRING CHAR AT END
LXI D,BKUPMSG ;ASK FOR THE DRIVE LETTER TO STORE IT TO
CALL QUESTION
CPI 1
JNZ START1 ;IF NO INPUT THEN START OVER
LDA INREC ;GET DRIVE LETTER TO STORE TO
STA BACKUPDRV
MSG1: LXI D,DATEMSG ;GET CURRENT DATE FOR REPORTS
CALL QUESTION ;PRINT MSG AND GET REPLY
CPI 8 ;8 CHAR MUST HAVE BEEN ENTERED
JNZ MSG1 ;REPEAT QUESTION IF NOT
LXI H,INREC ;MOVE DATE FROM INREC
; IF YOU DO NOT HAVE A CLOCK/DATE BOARD, REMOVE THE * FROM THE ABOVE
; LINES AND ASTERISK THE NEXT 2 LINES WHICH CALL THE CLOCK TO GET THE
; DATE
* CALL GETDATE ;GET DATE FROM CLOCK BOARD
* LXI H,DATETIME+1
MVI B,8 ;MOVE THE DATE TO A HOLD AREA
LXI D,DATE ;TO "DATE"
CALL MOVE
STRT1 LXI D,PRINTMSG ;CK FOR OUTPUT TO THE PRINTER
CALL QUESTION ;AND GET response
CPI 1
JNZ STRT1 ;NO INPUT THEN LOOP
LDA INREC ;GET ANSWER
CPI 'N'
JNZ START2
MVI A,0FFH ;SET PRNTFLG NONZERO FOR NO PRINTING
STA PRNTFLG
START2 LXI D,CORRMSG ;VERIFY ALL DATA IS CORRECT
CALL OUTPUT
LXI D,DRIVES ;GET DRIVES TO BACKUP
CALL OUT1 ;OUTPUT DRIVE LETTER CHAIN
LXI D,CORRMSG1
CALL OUT1
LDA BACKUPDRV ;GET DRIVE TO BACKUP TO BACK AGAIN
MOV E,A
MVI C,CONOUT
CALL BDOS ;OUTPUT DRIVE TO BACKUP TO OUT
LXI D,DATVERMSG ;GET DATE MESSAGE
CALL OUT1
LXI D,DATE ;THEN THE DATE ITSELF
CALL OUT1
LXI D,CORRY$N ;GET CORRECT MESSAGE
CALL QUESTION ;AND GET response
CPI 1
JNZ START2 ;NO INPUT THEN LOOP
LDA INREC ;GET ANSWER
CPI 'Y'
JNZ START1
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 ;SORT THE MEMORY TABLE BY TYPE, FILE
;NAME, THEN DISK ID
MVI A,RECSIZE ;SETUP TO REMOVE DUPLICATE ENTRIES
STA COMPSIZE ;COMPARE ON ALL CHAR
CALL KILLDUPS ;REMOVE DUPLICATE ENTRIES
CALL REPORT ;PRINT ALL ENTRIES
MVI A,11 ;REMOVE FILES THAT ARE ON MULTIPLE DISKS
STA COMPSIZE
CALL KILLDUPS
CALL SELECT ;RESTRICT THE FILES TO BACKUP
MSG3 LXI D,BACKQUS ;ASK IF YOU WANT BACKUP FUNCTION
CALL QUESTION
CPI 1
JNZ MSG3
LDA INREC
CPI 'N'
JZ FINISHED
CPI 'Y'
JNZ MSG3
CALL BACKUP ;BACKUP THOSE FILES REPORTED ON
FINISHED MVI C,0
JMP BDOS ;RESET AND RETURN TO CPM
*
* THE EXTRACT ROUTINE SCANS ALL THE DRIVES IN THE DRIVE TABLE
* WHEN COMPLETE, IT ASKS FOR THE NEXT DRIVE ID
* WHEN THE HARD DISK IS UP, IT WILL NOT ASK FOR THE DRIVE ID BUT
* WILL AUTOMATICALLY SCAN THE THREE HARD DISKS AND FINISH WITHOUT
* EVER ASKING FOR THE DRIVE ID.
*
* THE DUMMYFCB SETS UP A SKELETON TO READ ALL FILES ON THE DIRECTORY
*
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 LXI H,DRIVES ;GET ADDRESS OF THE DRIVE TABLE
SHLD ADDR1 ;TO SCAN
* MVI A,NODRV+1 ;SET UP COUNTER FOR THE NUMBER TO SCAN
* STA MAX1
NEXTDRV LDA MAX1 ;SEE IF THERE ARE MORE DRIVES TO SCAN
DCR A
STA MAX1 ;RETURN WHEN ALL HAVE BEEN SCANNED
RZ
LHLD ADDR1 ;GET ADDRESS OF DRIVE TABLE
MOV A,M ;GET DRIVE CHARACTER
STA RDISK
ANI 1FH ;CONVERT A=1...P=16
STA DUMMYFCB ;SET IN DR OF DUMMYFCB
INX H ;SET FOR NEXT READ OF DRIVE TABLE
SHLD ADDR1
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
JZ NEXTDRV ;NO MORE ENTRIES ON THIS DRIVE
JMP GETFCB ;EXTRACT DATA FROM FCB
NEXTFCB LXI D,DUMMYFCB ;GET NEXT ENTRY AFTER THE FIRST
MVI C,12H
CALL BDOS
INR A
JZ NEXTDRV ;NO MORE DIRECTORIES ON THIS DISK
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
IF NOT MOLEC
PUSH H ;SAVE IT FOR A MIN
LXI H,RFILE+4 ;GET FILE NAME TO CK FOR 'F4' TAGED
MOV A,M
POP H ;GET IT BACK
ENDIF
ANI 80H ;CK TO SEE IF WE SHOULD BACKUP THIS FILE
JNZ NEXTFCB ;BY CHECKING 'T3' FOR MOLECULAR COMPUTERS
;OR 'F4' FOR OTHER COMPUTERS
INX H ;POSITION TO THE EXTENT NUMBER
INX H
INX H
MOV A,M ;GET THE EXTENT
if diagnst
ORI 30H ;DIAGNOSTIC DISPLAY
STA RDISK+1
LXI D,RTYPE
CALL OUTPUT
LDA RDISK+1
ANI 0FH
endif
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
* 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 D,SORTMSG ;PUT OUT A MESSAGE SO THE USER DOES
CALL OUTPUT ;NOT THINK THIS CRASHED WHILE SORTING
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
* REPORT PRINTS THE SORTED CONSOLIDATED DIRECTORY ENTRIES.
* LINESPAGE IS THE NUMBER OF LINES PER PAGE AND RECLINE IS THE
* NUMBER OF 20 BYTE ENTRIES PER LINE. EACH TYPE BEGINS ON A
* NEW PAGE.
REPORT: LHLD TABCNT ;SET COUNT OF ENTRIES
INX H ;PLUS ONE
SHLD LASTTYPE ;INIT LASTTYPE TO INVALID DATA
SHLD MAX1 ;TO DECREMENT FIRST
LXI H,RAM-RECSIZE ;SET STARTING ADDRESS
SHLD ADDR1
CALL HEADING
NEXTPRT LHLD ADDR1
LXI D,RECSIZE ;SET TO ADD THE REC LENGTH
DAD D
SHLD ADDR1
LHLD MAX1 ;DECREMENT COUNT TO SEE WHEN DONE
DCX H
SHLD MAX1
LXI D,0000 ;SEE IF REACHED ZERO YET
CALL COMPREG
JZ TOPPAGE ;GO TO TOP OF NEXT PAGE
LHLD ADDR1 ;CURRENT TYPE = LAST TYPE?
MVI B,3 ;COMPARE 3 CHARACTERS
LXI D,LASTTYPE
CALL COMPARE
JNZ SKIP3 ;NEW TYPE ON NEW PAGE
PRNTNOW LDA MAX2 ;DECREMENT RECORDS PER LINE
DCR A
STA MAX2
JZ NEWLINE ;LINE FULL, GO TO NEW LINE
CALL FORMAT
LXI D,PRNTREC
CALL LIST
JMP NEXTPRT
SKIP3 LDA LINECNT
DCR A
JZ NEWPAGE
DCR A
JZ NEWPAGE
DCR A
JZ NEWPAGE
STA LINECNT
LXI D,CRLFLFLF
CALL LIST
JMP CHKTYPE
NEWPAGE CALL HEADING
CHKTYPE LXI D,LASTTYPE ;SET LAST TYPE TO CURRENT TYPE
LHLD ADDR1
MVI B,3
CALL MOVE
SETCNT MVI A,RECLINE+1
STA MAX2
JMP PRNTNOW
NEWLINE LXI D,CRLF
CALL LIST
LDA LINECNT
DCR A
STA LINECNT
JZ NEWPAGE ;PAGE FULL
JMP SETCNT
TOPPAGE LXI D,CRLF ;###
CALL LIST ;###
RET
* THE PURPOSE OF SELECT IS TO CREATE A FINAL LIST OF FILES TO
* BACKUP. SINCE BACKING UP 26 MEG CAN BE QUITE LONG, THIS REDUCES
* THE LIST TO ONLY NECCESSARY FILES. IT ALSO ALLOWS A RESTART
* AT ANY FILE. IT WILL DELETE DUPLICATE FILE NAMES (FILES ON A:
* WILL BE USED SINCE THAT IS ASSUMED TO BE THE LATEST), AND
* WILL DELETE THE FILE TYPES LISTED IN THE SKIP TABLE. THEN IT
* WILL LIST EACH TYPE AND ASK IF YOU DO WANT TO BACK UP ALL OF
* THIS TYPE (Y), SKIP BACKING UP OF THE ENTIRE TYPE (N), OR
* SELECT CERTAIN FILES (S) TO BACK UP. IF THE SELECT OPTION IS
* CHOSEN, EACH FILE NAME WILL BE PRINTED AND YOU BE ASKED TO
* BACK UP THE FILE (Y), IGNORE THE FILE DURING THE BACKUP
* (N), OR CONTINUE (C) TO BACKUP ALL OF THE REMAINING FILES
* WITHIN THIS TYPE WITHOUT ASKING ANY FURTHER NAMES (USED FOR
* RESTART). AFTER THE LIST HAS BEEN REDUCED, IT WILL BE LISTED
* BEFORE THE BACKUP ACTUALLY BEGINS.
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
LDA COMPSIZE
MOV B,A
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
SELECT EQU $
NOWSELECT EQU $ ;LET USER ELIMINATE SOME
LXI H,RAM-RECSIZE ;INITIALIZE
SHLD ADDR1
SHLD LASTTYPE ;MAKE SURE LASTTYPE DOES NOT MATCH
NEXTENTRY LHLD ADDR1 ;GET NEXT RECORD IN TABLE
LXI D,RECSIZE
DAD D
SHLD ADDR1 ;INCREMENT TABLE ENTRY
CHKNEXT MOV A,M ;CHECK FOR THE END OF THE TABLE
CPI 1AH ;CNTL-Z IS AT END
JZ LISTBKUP ;LIST THE FINAL TABLE
LXI D,LASTTYPE ;SEE IF THE CURRENT TYPE IS THE
LHLD ADDR1 ;LAST TYPE
MVI B,3
CALL COMPARE
JZ CHKSELECT ;TYPES MATCH, CHECK FILE SELECT
CALL MOVE ;TYPES DON'T MATCH, MAKE THE
;LAST TYPE = CURRENT TYPE NOW
MVI C,NOSKIP+1 ;SEE IF THE NEW TYPE IS IN THE
LXI D,SKIPTYPE ;LIST OF FILE TYPES TO SKIP
MVI B,3
NEXTSKIP DCR C ;DECREMENT NO OF FILES TO SKIP
JZ FORMQUS ;FILE IS GOOD
LHLD ADDR1
CALL COMPARE
JZ SKIPALLTYPE ;FILE WAS ON THE SKIP LIST
INX D ;INCREMENT TO NEXT SKIP FILE
INX D
INX D
JMP NEXTSKIP
FORMQUS LXI D,QTYPE ;FORM THE QUESTION ABOUT WHETHER
LHLD ADDR1 ;TO SKIP THIS FILE TYPE OR NOT
MVI B,3 ;MOVE THE FILE TYPE TO THE
CALL MOVE ;QUESTION PRINT LINE
XRA A
STA SELFLAG ;RESET THE SELECT FLAG
REASK1 LXI D,QUEST1
CALL QUESTION ;ASK THE QUESTION ABOUT THE TYPE
CPI 1 ;ONE CHARACTER RESPONSE ALLOWED
JNZ REASK1
LDA INREC ;GET THE RESPONSE
CPI 'N'
JZ SKIPALLTYPE
CPI 'Y'
JZ SAVEALLTYPE
CPI 'S' ;S=SELECT CERTAIN FILES FROM THIS
JNZ REASK1 ;TYPE
MVI A,1 ;SET THE SELECT FLAG
STA SELFLAG ;TO ASK THE NEXT QUESTION
ASKFILE LHLD ADDR1 ;FORMAT A QUESTION TO ASK IF THIS
LXI D,QTYPE2 ;PARTICULAR FILE IS TO BE SAVED
MVI B,3
CALL MOVE
LXI D,QFILE2 ;MOVE THE FILE NAME TO THE QUESTION
INX H
INX H ;POSITION PAST THE FILE TYPE
INX H ;IN THE TABLE
MVI B,8
CALL MOVE ;MOVE THE NAME
LXI D,8 ;POSITION PAST NAME TO THE
DAD D ;DISK ID
LXI D,QDISK2 ;MOVE THE DISK ID
MVI B,IDSIZE
CALL MOVE
REASK2 LXI D,QUEST2 ;ASK THE FILE QUESTION
CALL QUESTION
CPI 1 ;ONLY A 1 CHAR RESPONSE ALLOWED
LDA INREC
JNZ REASK2
CPI 'C' ;CONTINUE WITH THE REST OF THE
JZ SAVEALLTYPE ;FILES WITHIN THIS TYPE - RESTART
CPI 'Y' ;SAVE THIS PARTICULAR FILE
JZ NEXTENTRY
CPI 'N'
JNZ REASK2
LHLD ADDR1 ;SHORTEN THE LIST BY ONE ENTRY
LXI D,RECSIZE
DAD D
SHLD ADDR2 ;SKIP THE LAST ONE
CALL MOVELIST ;MOVES THE LIST DOWN FROM ADDR1
;TO ADDR2
LHLD ADDR1
JMP CHKNEXT ;CHECK NEXT ENTRY
CHKSELECT LDA SELFLAG ;CHECK THE SELECT FLAG
ORA A ;IF NOT ZERO, ASK THE QUESTION
JNZ ASKFILE ;ABOUT EACH FILE
JMP NEXTENTRY
SKIPALLTYPE CALL FINDTYPE ;FIND THE NEXT TYPE NOT MATCHING
CALL MOVELIST ;THIS ONE AND MOVE THE LIST DOWN
LHLD ADDR1
JMP CHKNEXT ;TO SKIP THIS TYPE
SAVEALLTYPE CALL FINDTYPE ;SAVE ALL OF THIS TYPE
LHLD ADDR2 ;RESET THE ADDRESS TO THE NEXT
SHLD ADDR1 ;TYPE
JMP CHKNEXT
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
FINDTYPE LHLD ADDR1 ;FIND THE NEXT ENTRY
SHLD ADDR2 ;WITH A TYPE DIFFERENT
FINDIT LHLD ADDR2 ;THAN THE CURRENT TYPE
LXI D,RECSIZE
DAD D
SHLD ADDR2
MOV A,M ;STOP AT END OF THE TABLE
CPI 1AH
RZ
XCHG
LHLD ADDR1
MVI B,3
CALL COMPARE
RNZ
JMP FINDIT ;ADDR2 WILL HAVE THE ADDRESS OF
;THE NEXT TYPE WHEN FINISHED
LISTBKUP EQU $ ;LIST THE FILES TO BE BACKED
SHLD ADDR2 ;SAVE THE END OF THE TABLE FOR LATER
LXI H,RAM-RECSIZE
SHLD ADDR1
CALL HEADING2
NEXTONE LHLD ADDR1 ;PRINT THE NEXT TABLE ENTRY
LXI D,RECSIZE
DAD D
SHLD ADDR1 ;INCREMENT TO THE NEXT ENTRY
MOV A,M ;CHECK FOR THE END OF THE
CPI 1AH ;TABLE
RZ
CALL FORMAT ;FORMAT ENTRY
LXI D,PRNTREC
CALL LIST ;PRINT IT
LDA MAX2 ;SEE MORE WILL FIT ON THIS LINE
DCR A
STA MAX2
JZ LINEFULL
JMP NEXTONE
LINEFULL LXI D,CRLF
CALL LIST
LDA LINECNT
DCR A
STA LINECNT
JZ PAGEFULL
JMP SETLINE
PAGEFULL CALL HEADING2
MVI A,LINESPAGE
STA LINECNT
SETLINE MVI A,RECLINE
STA MAX2
JMP NEXTONE
HEADING2 LXI D,HEAD2
CALL LIST
LXI D,CRLF
CALL LIST
MVI A,LINESPAGE
STA LINECNT
MVI A,RECLINE
STA MAX2
RET
* BACKUP IS USED TO BACKUP THE FILES IN THE CREATED LIST. IT
* WILL NOT BACK UP ANY FILE THAT WILL NOT FIT ON ONE DISK ENTIRELY.
* THE FILES THAT IT BACKS UP WILL COME FROM ANY OF THE HARD DISKS,
* BUT NOT NECCESSARILY IN DISK ORDER, BUT RATHER ALPHABETICAL FILE
* NAME ORDER. IT WILL PROMPT FOR THE FLOPPY DISK ID AND PRINT A
* REPORT SHOWING THE FLOPPY ID AND THE FILES COPIED FOR INDEX.
* IF THE FILE WILL NOT FIT ON A DISK, IT WILL BE DELETED FROM THE
* DISK, THAT DISK CLOSED AND REMOVED, AND PROMPTED FOR A NEW DISK
* TO RECEIVE THE FILE. BLANK 1024 BYTE SECTORED DISKS SHOULD BE
* USED FOR BEST PERFORMANCE. WHEN ONE DISKETTE IS FULL, IT WILL
* PROMPT FOR A NEW ONE SO MANY DISKETTES CAN BE USED TO BACKUP
* THE HARD DISKS. IF IT IS NECESSARY TO ABORT DURING THIS PROCESS,
* USE THE RESTART CAPABILITY PROVIDED IN "SELECT". THE AREA
* FOR THE DISK BUFFER IS ALL OF RAM FROM THE END OF THE TABLE
* TO THE START OF BDOS.
BACKUP EQU $
CALL TOPOFFORM
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
LXI D,RECSIZE ;SET AN ADDRESS FOR THE SECOND ENTRY
DAD D ;NEXT ENTRY = CURRENT + RECSIZE
SHLD ADDR2 ;LATER, USE MOVELIST TO MOVE THE LIST
;DOWN FROM ADDR2 TO ADDR1 AFTER EACH FILE
;HAS BEEN COPIED. THIS IS SO THAT THE
;RAM BUFFER WILL EXPAND AS THE FILES ARE
;COPIED SO THAT COPYING WILL BE FASTER.
CALL MOUNT
JMP PASSMOVE
NEXTFILE EQU $
CALL MOVELIST
INX H ;NEW START OF READ/WRITE BUFFER
SHLD ADDR3
XRA A ;RESET THE FLAG FOR FILES TOO BIG
STA TOOBIG ;TO FIT ON ONE FLOPPY
PASSMOVE LXI H,RAM ;THE TABLE SHRINKS SO THE CURRENT
;ENTRY IS ALWAYS AT "RAM" BUT THE
;READ/WRITE BUFFER GROWS
MOV A,M
CPI 1AH
JZ DISMOUNT ;FINISHED
FORMFCB LXI D,HDFCB ;CLEAR THE FCB
MVI B,36
XRA A
ZEROFCB STAX D
INX D
DCR B
JNZ ZEROFCB
LXI H,RAM ;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
MOV A,M
ANI 1FH ;CONVERT A=1...P=16
STA HDFCB
LXI D,FPFCB ;COPY THE HDFCB TO THE FLOPPY FCB
LXI H,HDFCB
MVI B,36
CALL MOVE
LDA BACKUPDRV ;SET THE RECEIVING FLOPPY DRIVE NUMBER
ANI 1FH ;CONVERT FLOPPY DRIVE TO NUMBER
STA FPFCB
LXI D,HDFCB ;OPEN THE HD FILE
MVI C,0FH
CALL BDOS ;OPEN THE INPUT FILE
INR A
JZ NOTFOUND
LXI D,FPFCB ;DELETE THE FILE ON FLOPPY IF IT
MVI C,13H ;EXISTS
CALL BDOS
LXI D,FPFCB ;CREATE THE FILE ON FLOPPY
MVI C,16H
CALL BDOS ;MAKE FILE
INR A
JZ DISKFULL
LXI H,RAM
CALL FORMAT
LXI D,PRNTREC
CALL OUTPUT
COPYLOOP CALL LOADBUFF ;LOAD MEMORY WITH FILE
CALL WRITEBUF ;WRITE MEMORY FILE
LDA EOF ;DISPLAY THE STATUS
ADI 30H
MOV E,A ;CONSOLE OUTPUT
MVI C,2
CALL BDOS
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
IF MOLEC
LXI H,HDFCB+11 ;TAG 'T3' BYTE TO INDICATE BACKUPED
ENDIF
IF NOT MOLEC
LXI H,HDFCB+4 ;TAG 'F4' BYTE TO INDICATE BACKUPED
ENDIF
MOV A,M ;GET 'T3' BYTE FOR TAGING ON MOLECULAR
;OR 'F4' BYTE FOR OTHER COMPUTERS
ORI 80H ;SET THE BIT
MOV M,A ;PUT IT BACK IN HDFCB
LXI D,HDFCB ;SETUP FOR ATTRIBUTE SETTING
MVI C,1EH
CALL BDOS ;WRITE IT ON THE DISK
LXI H,RAM
CALL PRINTFILE ;WRITE FILE NAME ON INDEX LIST
JMP NEXTFILE
DISKFULL LXI D,FPFCB
MVI C,13H ;DELETE FILE ON FLOPPY
CALL BDOS
LDA TOOBIG ;IS THIS THE SECOND FLOPPY
ORA A ;IT HAS TRIED TO COPY TO?
JZ FIRSTTRY ;NO, FIRST FLOPPY. RETRY
LXI D,BIGMSG ;YES, SECOND FLOPPY. SEND MESSAGE
CALL LIST ;WARNING THAT THIS FILE CANNOT
LXI H,RAM
CALL FORMAT ;BE BACKED UP WITH THIS PROGRAM
LXI D,PRNTREC
CALL LIST ;PRINT THE FILE NAME ALSO
CALL MOUNT
JMP NEXTFILE
FIRSTTRY INR A ;SET INDICATOR THAT IT HAS TRIED
STA TOOBIG ;ONCE ALREADY TO COPY IT
CALL MOUNT ;GET NEW DISK
JMP FORMFCB
NOTFOUND LXI H,RAM
CALL FORMAT
LXI D,NFMSG
CALL OUTPUT
LXI D,PRNTREC
CALL OUTPUT
RET
DISMOUNT CALL BELL
LXI D,DMNTMSG ;DISMOUNT FLOPPY
CALL QUESTION
DISM1 LXI D,AGAINMSG
CALL QUESTION ;AND GET response
CPI 1
JNZ DISM1 ;NO INPUT THEN LOOP
LDA INREC ;GET ANSWER
CPI 'Y'
JZ START ;IF YES THEN START OVER
CALL TOPOFFORM
RET
* ASSORTED ROUTINES
PRINTFILE CALL FORMAT
LXI D,PRNTREC ;PRINT THE FILE ENTRY
CALL LIST
LDA MAX2
DCR A
STA MAX2 ;ENTRIES PER LINE COUNTER
RNZ
LXI D,CRLF ;GO TO NEW LINE
CALL LIST
MVI A,RECLINE
STA MAX2
RET
HEADING3 LXI D,CRLFLFLF ;INDEX HEADING NOT AT TOP OF FORM
CALL LIST
LXI D,IDISKNO ;MOVE THE DISK ID NO TO HEADING
LXI H,VOLSER
MVI B,3
CALL MOVE
LXI D,IDATE
LXI H,DATE
MVI B,8
CALL MOVE
LXI D,INDEX
CALL LIST
LXI D,CRLF
CALL LIST
MVI A,RECLINE
STA MAX2
MVI A,LINESPAGE
STA LINECNT
RET
TOPOFFORM:
LDA PRNTFLG ;SEE IF PRINTER IS ON
ORA A
RNZ ;IF ZERO THEN PRINTER IS ON
MVI E,0dH ;### finish current line
MVI C,5 ;###
call BDOS ;###
MVI E,0CH ;POSITION PRINTER TO TOP OF FORM
MVI C,5
JMP BDOS
MOUNT CALL BELL
LXI D,MNTMSG
CALL QUESTION
CPI 3
JNZ MOUNT
LXI H,INREC
LXI D,ENDLIT
MVI B,3
CALL COMPARE
JZ FINISHED
LXI D,VOLSER
LXI H,INREC
MVI B,3
CALL MOVE ;MOVE VOLSER ID TO VOLSER
MVI C,0DH ;DO A SYSTEM RESET TO CHANGE DISKS
CALL BDOS
ERA LXI D,ERASE
CALL QUESTION
CPI 1
JNZ ERA
LDA INREC
CPI 'N'
JZ NOERA
CPI 'Y'
JNZ ERA
LDA BACKUPDRV
ANI 1FH
STA DUMMYFCB
MVI C,13H
LXI D,DUMMYFCB
CALL BDOS ;DELETE ALL FILES ON FLOPPY
NOERA EQU $
CALL HEADING3
LXI D,FPFCB ;CLEAR THE FCB TO CREATE A FILE NAME
MVI B,36
XRA A
CLRFCB STAX D
INX D
DCR B
JNZ CLRFCB
LDA BACKUPDRV ;SET UP THE DRIVE AS THE BACKUP
ANI 1FH ;CONVERT FLOPPY DRIVE TO NUMBER
STA FPFCB
LXI H,DATE ;CREATE A NULL FILE WITH THE DATE AS
LXI D,FPFCB+1 ;THE FILE NAME AND THE 3 DIGIT
MVI B,8
CALL MOVE
LXI H,VOLSER ;3 DIGIT VOLSER AS THE FILE TYPE
LXI D,FPFCB+9
MVI B,3 ;THIS FILE WILL BE USED TO IDENTIFY
CALL MOVE ; THE DISK AND MARK THE DATE
LXI D,FPFCB
MVI C,16H ;CREATE THE FILE
CALL BDOS
INR A
JZ MOUNT ;DISK FULL?
LXI D,FPFCB
MVI C,10H ;CLOSE THE FILE
CALL BDOS
RET
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
BELL EQU $
MVI C,9
LXI D,MSG
CALL BDOS
BEEP:
* MVI C,5 ;BELL ON PRINTER
* MVI E,07H
* CALL BDOS
MVI C,2 ;07H ON CRT
MVI E,07H
CALL BDOS
bepe: MVI C,0BH
CALL BDOS ;GET CONSOLE STATUS
ORA A
JZ BEPE
MVI C,01
CALL BDOS ;GET THE DUMMY CHAR
RET
MSG DB 0DH,0AH,0AH,'PRESS ANY KEY TO CONTINUE'
DB 0DH,0AH,0AH,'$'
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
LXI D,PRNTREC ;MOVE THE DISK ID TO THE LINE
MVI B,IDSIZE
CALL MOVE
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
HEADING LXI D,HEAD1
CALL LIST
LXI D,DATE
CALL LIST
LXI D,TABFULL
LDA ABORT
ORA A
CNZ LIST
MVI A,LINESPAGE
STA LINECNT
LXI D,CRLF
CALL LIST
LXI D,CRLF
JMP LIST
LIST PUSH H ;THIS DIFFERS FROM OUTPUT
PUSH B ; IN THAT LIST GOES TO THE
PUSH D ;LIST DEVICE AND OUTPUT GOES
LDA PRNTFLG ;CK FOR PRINTER OUTPUT
ORA A ;IF ZERO THEN PRINT ELSE JUMP AROUND
JNZ LIST2
LIST1 LDAX D ;TO THE CONSOLE DEVICE
CPI '$'
JZ LIST2
INX D
PUSH D
MOV E,A
MVI C,5
CALL BDOS
POP D
JMP LIST1
LIST2 POP D
POP B
POP H
RET
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
ora a ;### added by wfd, 6/3/84
rz ;### nope, return anyway
push psw ;###
push b ;###
push h ;###
lxi h,inrec ;###
mov b,a ;###
touppr: mov a,m ;###
cpi 'a' ;### lower case ?
jc toupdn ;### no
cpi '{' ;### 'z' or less?
jnc toupdn ;### no
ani 5fh ;### make upper
mov m,a ;###
toupdn: inx h ;###
dcr b ;###
jnz touppr ;###
pop h ;###
pop b ;###
pop psw ;###
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
; THIS ROUTINE READS THE COMPUTIME CLOCK AND FORMATS THE TIME AND DATE
GETDATE EQU $
MVI A,16 ;RAISE THE HOLD SIGNAL
OUT C2
MVI A,50 ;DELAY AT LEAST 50 MILLISECONDS
WAIT50 DCR A
JNZ WAIT50
LXI H,DATETIME ;SET MESSAGE START. NOTE 1ST CHAR IS SPACE
MVI A,42 ;GET MONTH TENS CHAR
CALL GETTIME
MVI A,41 ;GET MONTH UNITS CHAR
CALL GETTIME
INX H ;SKIP SLASH
MVI A,40 ;GET DAY TENS CHAR
CALL GETTIME
ANI 0F3H ;DROP LEAP YEAR INDICATOR
MOV M,A
MVI A,39 ;GET DAY UNITS CHAR
CALL GETTIME
INX H ;SKIP SLASH
MVI A,44 ;GET YEAR TENS CHAR
CALL GETTIME
MVI A,43 ;GET YEAR UNITS CHAR
CALL GETTIME
INX H ;SKIP BLANK
MVI A,37 ;GET HOUR TENS CHAR
CALL GETTIME
ANI 0F3H ;DROP AM/PM AND 24HR INDICATORS
MOV M,A
MVI A,36 ;GET HOUR UNITS CHAR
CALL GETTIME
INX H ;SKIP COLON
MVI A,35 ;GET MINUTES TENS CHAR
CALL GETTIME
MVI A,34 ;GET MINUTES UNITS CHAR
CALL GETTIME
INX H ;SKIP COLON
MVI A,33 ;GET SECONDS TENS CHAR
CALL GETTIME
MVI A,32 ;GET SECONDS UNITS CHAR
CALL GETTIME
XRA A
OUT C2 ;LOWER HOLD SIGNAL
RET
C1 EQU 254 ;CLOCK ADDRESS PORT
C2 EQU 253 ;CLOCK DATA OUTPUT PORT
GETTIME INX H ;ADVANCE TO NEXT PRINT POSITION
OUT C1
MVI A,6 ;DELAY AT LEAST 6 MILLISECONDS
WAIT6 DCR A
JNZ WAIT6
IN C1
ORI 30H ;CONVERT TO ASCII
MOV M,A
RET
DATETIME DB ' 00/00/00 HH:MM:SS$'
DRIVES DB 'ABCDEFGHIJKLMNOP' ;DRIVE NOS FOR THE HARD DISKS
BACKUPDRV DS 1 ;BACKUP FLOPPY DRIVE LETTER
SIGNON DB 1AH,'HARD DISK CATALOG AND BACKUP v2.3 8/22/83 rds$'
DRIVMSG DB 0AH,'Enter Letter of Drives to Backup from as "ABCD..ect."? $'
BKUPMSG DB 0AH,'Enter Letter of Floppy Drive to Backup to? $'
CORRMSG DB 0AH,'Backing up Drives $'
CORRMSG1 DB ' to Floppy Drive $'
PRINTMSG DB 0AH,'Do you wish a Printed Report (Y/N)? $'
CORRY$N DB 0AH,'Is this Correct (Y/N)? $'
DATEMSG DB 0AH,'Enter 8 Char Date for Reports (MM/DD/YY)? $'
DATVERMSG DB ' for Date $'
ERASE DB 0AH,07H,'ERASE Floppy Disk First (Y/N)? $'
TABFULL DB 0AH,07H,'MEMORY FULL...REPORT NOT COMPLETE$'
BACKQUS DB 0AH,'Begin Backup Procedure (Y/N)? $'
SORTMSG DB 0AH,'SORTING...$'
NFMSG DB 0AH,07H,'FILE NOT FOUND...ABORTING$'
DMNTMSG DB 'DISMOUNT BACKUP DISK AND ENTER RETURN$'
AGAINMSG DB 0AH,'Do you wish to run Backup again (Y/N)? $'
MNTMSG DB 'MOUNT DISKETTE FOR BACKUP AND ENTER '
DB '3 CHAR DISK ID OR "END"? $'
ENDLIT DB 'END'
VOLSER DS 3
QUEST1 DB 'BACKUP ALL FILES OF TYPE '
QTYPE DS 3
DB ', (Y/N/S)? $'
QUEST2 DB 'BACKUP FILE NAMED '
QDISK2 DS 1
DB ':'
QFILE2 DS 8
DB '.'
QTYPE2 DS 3
DB ', (Y/N/C)? $'
HEAD2 DB 0CH,'THE FOLLOWING FILES WILL BE COPIED TO DISKETTES$'
PRNTFLG DS 1
PRNTREC DS 1
DB ':'
PRNFILE DS 8
DB '.'
PRNTYPE DS 3
DB ' $'
CRLFLFLF DB 0DH,0AH,0AH,0AH,'$'
INDEX DB 'THE FOLLOWING FILES ARE ON DISKETTE NO. '
IDISKNO DS 3
DB ' AS OF '
IDATE DS 8
DB '$'
CRLF DB 0DH,0AH,'$'
HEAD1 DB 0CH,'CONSOLIDATED INDEX BY FILE TYPE AS OF $'
DATE DS 8
DB ' $'
BIGMSG DB 0DH,0AH,'FILE TOO LARGE TO FIT ON ONE DISKETTE '
DB 'SO NOT BACKED UP **** $'
HDFCB DS 1
HDFILE DS 8
HDTYPE DS 3
DS 24
FPFCB DS 36
TOP DB 0CH,'$'
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
RAM EQU $
BDOS EQU 05H
CONIN EQU 01H
CONOUT EQU 02H
END 100H
*)('&%$#"!