;*********************************************************************
;
; BU.ASM - BACKUP UTILITY - 12/08/1984 Version 1.0
; (c) 1984 by Kim Levitt - MBBS HQ RCP/M
;
; Permission is granted to distribute this program, in source
; and/or object code form and the associated documentation
; file in the Public Domain for the benefit of CP/M hard disk
; system owners. If you appreciate this program, please
; consider donating $10 or more to my efforts in public domain
; software and also to keep my RCP/M system running. Please
; send donations to: Micro Bulletin Board Systems; 8033 Sunset
; Blvd., #975; Los Angeles, CA 90046. Make checks payable to:
; "Micro Bulletin Board Systems".
;
; -- Kim Levitt 12/08/84
;
;*********************************************************************
;
; Loosely based on:
;
; NEWBACK - DISK DIRECTORY AND BACKUP PROGRAM - 11/20/83
; (c) 1980 by GARY YOUNG
;
; (it's so different I could have almost as easily have
; started from scratch, but I did use Gary's sort routine and
; other goodies so credit where credit is due, but this entire
; program is not copyright by Gary, only parts of it. I claim
; copyright on other code I have added and the entire program
; as a whole, but offer this freely in the Public Domain.
; Kudos also to Irv Hoff, Alex Soya, Ron Stevenson and Jim
; Gronek for their contributions to the public domain BAK25KP
; program on which BU was based.)
;
;=======================================================================
; 01/16/85
; (V1.2) If you are using RBYANC as a catalog program, then set
; the RBYANC flag to 'YES'. See 'RBYANC EQU' for details
; Fixed page length problem. Added
; top-of-forms where needed for printer. Spaced headings
; on printed list. Added 6 to left margin (ident6) and
; increased number of columns. (Makes it easier to fit
; into notebook). Added more bells, (I sometimes don't pay
; attention). Included choice of printout, compressed
; (132 columns), or normal (80 columns), and printer es-
; cape sequences, if desired . Set flag
; to activate and insert proper printer code if desired.
; DEC LA50 code included for compressed printout.
;
; Thanks for a great program !!!
; Greg Teater
; Field Service Engineer
; Digital Equipment Corp.
; 614-868-1900 x264
;
;
; 01/01/85 Keep File-attributes, when backing up to floppy - more in
; (V1.1) synch with NSWEEP.Corrected SPACE-routine and added "xx K
; left" output for floppy. BGE (Eiben at DEC-Marlboro)
;
; 12/08/84
; (V1.0) New universal version (stripped out hardware-specific
; code) Other improvements to point where it now works
; like it should. (Needs at least v2.2 CP/M however, as
; it uses the GETDPB and CFILSZ functions of BDOS which I
; don't believe were available in v1.4.) I also stripped
; out the selection option and a few other things, this
; beastie is so different now I changed the name to BU
; (Backup Utility). It is mainly for ZCPR/ZCPR2/ZCPR3
; hard disk systems as it sorts things by DISK/USER
; instead of file type as in the old BAK25KP on which this
; was based. Used in conjunction with NSWP (to reset
; and/or set the A attribute bit on files and/or for
; restoring crashed files or disks from backup floppies),
; it is a pretty nifty utility to have handy.
; - Kim Levitt
;
;=======================================================================
;
; Beginning of Equates
;
YES EQU 0FFH
NO EQU 0
;
;
; User-Selectable Equates
;
RBYANC EQU YES ;set to 'YES' if using RBYANC as catalog program v1.2
;volume label on floppy will have this format v1.2
; '--BACKUP.xxx' where xxx is the output volume v1.2
;name given at backup time. The date will also v1.2
;be on output floppy but as the second file v1.2
;format '+YYMMDDy.xxx'. where 'y' is the input v1.2
;drive letter and 'xxx' is the output vol. label v1.2
;
CLOCK EQU NO ;yes if clock is installed.
;
; NOTE: If you set CLOCK YES, be sure to include the proper
; GETDATE and support routines in the IF CLOCK area at the
; end. (This hardware specific code was taken out into
; separate "overlay files" to prevent this thing from getting
; out of hand.)
;
COMPRES EQU YES ;88 lines/page & 132 columns v1.2
NORMAL EQU NO ;66 lines/page & 80 columns v1.2
;
; NOTE: Must select either COMPRESS or NORMAL but not both v1.2
;
PRNTSET EQU YES ;send printer dependent escape seq v1.2
;check SETPRINTER v1.2
;
;*****************************************************************************
;
IF COMPRES
LINSPG EQU 88 ;lines per page for consolidated list v1.2
RECLIN EQU 5 ;entries per line - consolidated list v1.2
RECLN2 EQU 5 ;entries per line - diskette list v1.2
ENDIF
;
IF NORMAL
LINSPG EQU 66 ;lines per page for consolidated list v1.2
RECLIN EQU 4 ;entries per line - consolidated list v1.2
RECLN2 EQU 3 ;entries per line - diskette list v1.2
ENDIF
;
BASE EQU 0 ;Normal CP/M BASE = 0
;
; Equates NOT usually User-modified
;
IDSIZE EQU 1 ;id now means a:, b:, c:, etc
RECSIZ EQU 13 ;record layout as follows
; diskid = 1 byte
; user# = 1 byte (binary 0-15)
; file = 8 bytes
; type = 3 bytes
;
BEL EQU 07H ;console bell
BS EQU 08H ;backspace
BLANK EQU 20H ;space
CR EQU 0DH ;carriage return
LF EQU 0AH ;line feed
FF EQU 0CH ;form feed
ESC EQU 1BH ;escape
CTRLZ EQU 1AH ;eof (also clr screen on some systems)
;
BDOS EQU 05H
CONINP EQU 01H
CONOUT EQU 02H
LSTOUT EQU 05H
INPSTR EQU 0AH
CONSTC EQU 0BH
SYSRST EQU 0DH
SELDSK EQU 0EH
OPNFIL EQU 0FH
CLSFIL EQU 10H
SRC1ST EQU 11H
FNDNXT EQU 12H
DELFIL EQU 13H
REDSEQ EQU 14H
WRTSEQ EQU 15H
MAKFIL EQU 16H
SETDMA EQU 1AH
GETALV EQU 1BH
SETATT EQU 1EH
GETDPB EQU 1FH
GETUSR EQU 20H
SETUSR EQU 20H
CFILSZ EQU 23H
;
;=======================================================================
;
; Start of program code and data
;
ORG BASE+100H ;Standard CP/M TPA location
;
JMP START
;
;***********************************************************************
;
; USER DEFINABLE DATA/CODE AREA
;
; (An escape sequence or control character may be patched in
; this location using DDT and SAVE without the need for a
; reassembly. I have allowed up to nine bytes for long escape
; sequences such as the VT100 ANSI mode clear screen/home
; cursor sequence: ESC [ 2 J ESC [ ; H. End the sequence with
; a null (00H) character.)
;
CLSMSG: DB ESC,'[','2','J',ESC,'[',';','H',0;clear screen msg goes here
;
SETPRINTER:
DB ESC,'[4w' ;DEC LA50 16.5 char/in. v1.2
DB ESC,'[2z',0 ;DEC LA50 8 lines/in. (88 lines/page) v1.2
; (You can set up this table to define the filetypes which you
; do not wish to have backed up..)
;
;
;
;
;
NOSKIP: DB 9 ;number of filetypes in skip list
SKPTYP: DB 'PRN' ;No PRINT-files
DB 'HEX' ;No intermediate HEX
DB 'SYM' ;No intermediate Symbols
DB 'BAK' ;No BAKup's
DB '$$$' ;No incompletes
DB 'TMP' ;No temporaries
DB 'BAD' ;No BADBLK allocations
DB 'SWP' ;no FW swap-files either
DB 'F$$' ;no FW intermediate Format-files
DS 25 ;allow extra room so can add to SKPTYP
;
; (You may have to change the routine below but probably not)
;
CLRSCRN:
LXI D,CLSMSG ;This simply outputs the above string.
CALL STROUT ;If you have a memory mapped display,
;you may have to write a new routine.
;
RET
;
;
; Program begins executing here
;
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 en-
STA EOF ;.. tries as possible
STA GOTONE ;flag shows no file found yet if zero
MVI E,0FFH ;Get current user #
MVI C,GETUSR ;using BDOS function
CALL BDOS ;so we know where we are...
STA CURUSR ;save it...
STA RUSR
CALL CONVRT
MOV A,B ;save for id to console
STA USERID
MOV A,C
STA USERID+1
;
START1:
;
CALL CLRSCRN ;clear the screen and set printer v1.2
LXI D,SIGNON ;print signon message
CALL OUTPUT
;
IF RBYANC ; v1.2
LXI D,SIGNON1 ;print 'RBYANC support' v1.2
CALL OUTPUT ;do it v1.2
ENDIF ;RBYANC v1.2
;
IF PRNTSET ; v1.2
LXI D,SIGNON2 ;print 'DEC printer support' may want v1.2
;to change this to match your printer v1.2
CALL OUTPUT ;do it v1.2
ENDIF ;PRNTSET v1.2
;
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 drives info
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
CPI 'A'
JC START1 ;ng if less than A also
INX H ;point to next
DCR B ;dec count
JNZ STRT ;loop
MVI M,0 ;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 exit program
LDA INREC ;get drive letter to store to
STA BACKUPDRV
;
START2: LXI D,CORRMSG ;verify all data is correct
CALL OUTPUT
LXI D,DRIVES ;get drives to backup
CALL STROUT ;output drive letter chain
LXI D,CORRMSG1
CALL STROUT
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,CORRY$N ;get correct message
CALL QUESTION ;and get responce
CPI 1
JNZ START2
LDA INREC ;get answer
CPI 'Y'
JNZ START1
;
LXI D,USRMSG ;ask if all users to back up
CALL QUESTION
CPI 1
JNZ START1 ;thats what you get for a wrong answer
LDA INREC ;get answer
CPI 'N'
JZ NOUSRS ;No?
CPI 'Y' ;do all user areas
JNZ START1 ;If neither Y nor N..
MVI A,0 ;set user 0 meaning do them all
JMP DONUSR
;
NOUSRS: MVI A,17 ;set user 17 meaning do only what we are
;
DONUSR: STA CURUSER
;
LXI D,TAGMSG ;ask if should skip F4 files
CALL QUESTION
CPI 1
JNZ START1 ;thats what you get for a wrong answer
LDA INREC ;get answer
CPI 'Y' ;skip files with F4 tag?
JZ SKPANS
CPI 'N'
JZ SKPANS
JMP START1 ;oops
;
SKPANS:
STA TAGFLG ;either Y or N
;
LXI D,SETF4Q ;ask if should set F4 after backup
CALL QUESTION
CPI 1
JNZ START1 ;thats what you get for a wrong answer
LDA INREC ;get answer
CPI 'Y' ;skip files with F4 tag?
JZ SETANS
CPI 'N'
JZ SETANS
JMP START1 ;oops
;
SETANS:
STA SETF4 ;either Y or N
;
IF NOT CLOCK
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
ENDIF ;NOT CLOCK
;
IF CLOCK
CALL GETDATE ;get date from clock board
LXI H,DATETIME+1
ENDIF ;CLOCK
;
MVI B,8 ;move date to hold area
LXI D,DATE ;to "date"
CALL MOVE
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: LDA GOTONE ;no file found fix
ORA A
JNZ ALLOK
LXI D,NOFILS ;no files message
CALL OUTPUT
JMP FINISHED ;as nothing to do we are done
;
ALLOK: CALL SORT ;sort by type, file name and disk id
CALL DONE
MVI A,RECSIZ ;setup to remove duplicate entries
STA COMPSIZE ;compare on all char
CALL KILLDUPS ;eliminate duplicate entries
CALL DONE
CALL REPORT ;print all entries
CALL DONE
;
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 TOPOFFORM ; v1.2
CALL BACKUP ;backup those files reported on
;
FINISHED:
;
CALL TOPOFFORM
LXI D,EXITBU
CALL OUTPUT
JMP 0000H ;Warm boot when done...
;
; the extract routine scans all the drives in the drive table when com-
; plete, 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 D,SCANMSG ;Tell user what's happening...
CALL OUTPUT
LXI H,DRIVES ;get address of the drive table
SHLD ADDR1 ;to scan
LDA CURUSER
STA SAVCUSR ;save CURUSER
;
NEXTDRV:
LDA MAX1 ;see if there are more drives to scan
DCR A
STA MAX1 ;next user/ret when all have been scanned
RZ
LHLD ADDR1 ;get address of drive table
MOV A,M ;get drive character
STA RDISK
STA DISKID
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,DISKDIS ;send disk id message
CALL STROUT
LDA SAVCUSR
STA CURUSER ;reset CURUSER
;
EXTRCTL:
LDA CURUSER ;get user number
CPI 16 ;check if we do them all
JNC EXTRCTC ;no users greater than 15
MOV E,A ;valid user so set it.
MVI C,SETUSR ;set user function
CALL BDOS ;tell cp/m to do some work !
LDA CURUSER
STA RUSR ;save it for format and
STA CURUSR ;hard disk select
CALL CONVRT
MOV A,B ;send id to console
STA USERID
MOV A,C
STA USERID+1
;
EXTRCTC:
LXI D,USERDIS
CALL STROUT
LXI D,DISKBUF ;set a dma address for directory entries
MVI C,SETDMA
CALL BDOS ;set dma
LXI D,DUMMYFCB ;get first directory entry
MVI C,SRC1ST
CALL BDOS ;get directory
INR A
JZ NEXTUSR ;no more entries in this user #
JMP GETFCB ;extract data from fcb
;
NEXTFCB:LXI D,DUMMYFCB ;get next entry after the first
MVI C,FNDNXT
CALL BDOS
INR A
JZ NEXTUSR ;no more directories in this user #
;
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,11 ;move 11 characters
CALL MOVE
;
LDA TAGFLG
CPI 'Y' ;skipping 'F4' files?
JNZ STRIPIT ;if not, no need to check F4 bit
LDA RFILE+3 ;chk 'F4' bit
ANI 80H ;ck to see if we should backup this file
JZ STRIPIT ;if no F4 bit, continue
JMP NEXTFCB ;else, forget this one...
;
STRIPIT:
LXI H,RFILE ;strip off the high bit set by
MVI B,11 ;the version program
CALL STRIP
LXI D,SKPTYP
MVI B,3
LDA NOSKIP
INR A
MOV C,A
;
NEXTSKIP:
DCR C
JZ DOIT
LXI H,RTYPE
CALL COMPARE
JZ NEXTFCB
INX D
INX D
INX D
JMP NEXTSKIP
;
DOIT:
LXI H,RFILE ;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:
MVI A,0FFH
STA GOTONE ;set flag that we have at least one entry
LHLD TABADDR ;get memory table address
LXI D,RDISK ;get memory record address
XCHG ;rtype (hl) to tabaddr (de)
MVI B,RECSIZ ;move recsiz bytes
CALL MOVE
LHLD TABADDR ;increment for next entry
LXI D,RECSIZ ;recsiz bytes in record
DAD D
SHLD TABADDR ;save new address
MVI M,CTRLZ ;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+recsiz
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
;
NEXTUSR:
LDA CURUSER
INR A
CPI 16 ;get user and see if another one to do
JNC NEXTDRV ;all done so lets go next disk
STA CURUSER ;else do next user
JMP EXTRCTL ;until done
;.....
;
;
; the following routine is a bubble sort. in pseudobasic this would be
; done as follows: sort addr1=bottom(ram)-recsiz (recsiz is count of
; bytes in one record)
;
; MAX1=0
;LOOP1: MAX1=MAX1+1
; ADDR1=ADDR1+RECSIZ (first time this would be the bottom)
; IF MAX1>TABCNT-1 THEN TO TO SORTED
; ADDR2=ADDR1
; MAS2=MAX1
;LLOP2: MAX2=MAX2+1
; ADDR2=ADDR2+RECSIZ
; IF MAX2>TABCNT THEN GO TO LOOP1
; IF TABLE(ADDR1)
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,RECSIZ ;the outer loop and increment
DAD D ;by recsiz 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,RECSIZ
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. linspg is
; the number of lines per page and reclin is the number of 20 byte en-
; tries per line. each type begins on a new page.
;
REPORT:
;
IF PRNTSET ;user defined printer functions v1.2
LXI D,SETPRINTER ;This outputs the control setup characters v1.2
CALL LIST ;for printer, check SETPRINTER v1.2
ENDIF ; v1.2
;
LXI D,RPTING
CALL OUTPUT
LHLD TABCNT ;set count of entries
INX H ;plus one
SHLD MAX1 ;to decrement first
LXI H,RAM-RECSIZ ;set starting address
SHLD ADDR1
CALL HEADING
;
NEXTPRT:LHLD ADDR1
LXI D,RECSIZ ;set to add the receive 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
RZ ;return if done
LHLD ADDR1 ;current disk = last disk?
LDA LASTDSK
CMP M
JNZ SKIP3 ;new disk, skip 3 lines
INX H
LDA LASTUSR
CMP M
JNZ SKIP3 ;new user, skip 3 lines
;
PRNTNOW:MVI B,RECLIN+1 ;find # records per line v1.2
LDA MAX2 ;find which column of print is current v1.2
CMP B ;are they equal v1.2
JZ COLUMN1 ;yes, bypass tab printing v1.2
LXI D,TAB ;add spaces between file names v1.2
CALL LIST
COLUMN1:LDA MAX2 ;decrement records per line
DCR A
STA MAX2
JZ NEWLINE ;line full, go to new line
LHLD ADDR1
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
CALL MARGIN ;add print margin v1.2
JMP CHKDISK
;
NEWPAGE:
CALL TOPOFFORM
CALL HEADING ;print top of form message
;
CHKDISK:
LHLD ADDR1
MOV A,M
STA LASTDSK
INX H
MOV A,M
STA LASTUSR
;
SETCNT: MVI A,RECLIN+1
STA MAX2
JMP PRNTNOW
;
NEWLINE:LXI D,CRLF
CALL LIST
CALL MARGIN ;put in print margin v1.2
LDA LINECNT
DCR A
STA LINECNT
JZ NEWPAGE ;page full
JMP SETCNT
;
KILLDUPS:
LXI D,KILDUP
CALL OUTPUT
LXI H,RAM
SHLD ADDR1 ;set the start of the table
;
NEXTEQUAL:
LHLD ADDR1 ;check each entry against the next
LXI D,RECSIZ
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,RECSIZ
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 CTRLZ
RZ
;
INX H
INX D
JMP MOVENEXT
;
;.....
;
BACKUP: 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,RECSIZ ;set an address for the second entry
DAD D ;next entry = current + recsiz
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.
MVI A,0FFH
STA LASTDSK ;initialize LASTDSK for first STRTMSG
;
OKMOUNT:CALL MOUNT
;
NOMNT: JMP PASSMOVE
;
NEXTFILE:
CALL MOVELIST
INX H ;new start of read/write buffer
SHLD ADDR3
;
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 CTRLZ
JZ FINI ;finished
;
LDA LASTDSK
CMP M ;are we on a new disk?
JZ FORMFCB ;nope, continue
LXI D,FINIMSG
CALL BCKMSG ;else say end of disk X
JMP NEWDISK ;and mount a new floppy
;
FORMFCB:
LXI H,RAM
CALL FORMAT ;Format filename now
MVI A,' '
STA PRNTSIZ
STA PRNTSIZ+1
STA PRNTSIZ+2 ;(clear out "size" area)
MVI A,0
STA PRNTSIZ+3 ;(don't know size yet)
;
LXI D,HDFCB ;clear the fcb
MVI B,36
XRA A
;
ZEROFCB:
STAX D
INX D
DCR B
JNZ ZEROFCB
LXI H,RAM+2 ;get address of table entry
LXI D,HDFILE ;move in the filename & type
MVI B,11
CALL MOVE
LDA RAM
ANI 1FH ;convert a=1...p=16
STA HDFCB
LDA RAM+1 ;get user
STA CURUSR ;save it
MOV E,A
MVI C,SETUSR ;set it
CALL BDOS
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
;
LDA HDFCB ;get Hard disk drive
SUI 1 ;convert for BDOS
MOV E,A ;stick in E
MVI C,SELDSK ;call Select disk
CALL BDOS ;(for dumb systems w/o auto select)
;
LXI D,HDFCB ;open the hd file
MVI C,OPNFIL
CALL BDOS ;open the input file
INR A
JZ NOTFOUND
;
LXI D,HDFCB ;compute file size
MVI C,CFILSZ ;(in sectors)
CALL BDOS
LDA FLSFAC ;get shift factor
ADI 3 ;change from Kb shift to sect shift
LXI H,1 ;set 0 bit on
CALL FRS ;shift HL left A bits
DCX H ;decrement 1
XCHG ;stick in DE
LHLD HDFCB+33 ;get file size in sectors
DAD D ;add value for round up
CALL DVHL8 ;convert to K (w/floppy blocking)
SHLD HDFLSZ ;save file size in K
LXI H,1 ;figure KB mask
CALL SHIFT
DCX H
MOV A,L
CMA ;ignore lower FLSFAC bits
MOV L,A
LDA HDFLSZ
ANA L
STA HDFLSZ ;(we added extra for round up)
;
LXI H,PRNTSIZ+3 ;initial KPTR
SHLD KPTR
LHLD HDFLSZ
CALL KOUT
;
XRA A
STA HDFCB+32 ;make sure current rec cleared
STA HDFCB+33 ;for sequential reading
STA HDFCB+34
STA HDFCB+35
LHLD HDFLSZ ;get filesize back again...
XCHG
LHLD FLMXKB ;compare with max space on floppy
CALL SBHLDE ;see if too big to backup
JC TOOBIG
;
LDA FPFCB ;get Floppy disk drive
SUI 1 ;convert for BDOS
MOV E,A ;stick in E
MVI C,SELDSK ;call Select disk
CALL BDOS ;(for dumb systems w/o auto select)
;
LXI D,FPFCB ;delete the file on floppy if it
MVI C,DELFIL ;exists
CALL BDOS
;
CALL SPACE ;get space available on floppy
LHLD HDFLSZ ;if not too big, see if enuf room now
XCHG
LHLD FLFREE
CALL SBHLDE
JC DISKFUL2
;
LXI D,FPFCB ;create the file on floppy
MVI C,MAKFIL
CALL BDOS ;make file
INR A
JZ DISKFULL
;
LXI H,RAM
CALL FORMAT
LXI D,BCKUM
CALL OUTPUT
LXI D,PRNTREC
CALL STROUT
LXI D,BCKUM2
CALL STROUT
LDA BACKUPDRV
STA PRNDISK
MVI A,0
STA PRNFILE
LXI D,PRNTREC
CALL STROUT
LDA RAM
STA PRNDISK
LDA RAM+2
STA PRNFILE
LXI D,BCKUM3
CALL STROUT
;
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,CLSFIL
CALL BDOS ;close
LXI D,FPFCB+1 ;copy attributes from HDFCB to FPFCB V1.1
LXI H,HDFCB+1 ;..we want to keep them V1.1
MVI B,13 ; V1.1
CALL MOVE ; V1.1
MVI C,SETATT ; V1.1
LXI D,FPFCB ; V1.1
CALL BDOS ;Set attributes a'la HDFCB on floppy V1.1
;
LDA SETF4 ;do we want to set attr?
CPI 'Y'
JNZ NOSETF4 ;if no, skip that code..
;
LXI H,HDFCB+4 ;tag 'F4' byte to indicate backuped
MOV A,M
ORI 80H ;set the bit
MOV M,A ;put it back in hdfcb
;
LDA HDFCB ;get Hard disk drive
SUI 1 ;convert for BDOS
MOV E,A ;stick in E
MVI C,SELDSK ;call Select disk
CALL BDOS ;(for dumb systems w/o auto select)
;
LXI D,HDFCB ;setup for attribute setting
MVI C,SETATT
CALL BDOS ;write it on the disk
;
NOSETF4:
LXI H,RAM
CALL PRINTFILE ;write file name on index list
CALL DONE
JMP NEXTFILE
;
DISKFULL:
LXI D,FPFCB
MVI C,DELFIL ;delete file on floppy
CALL BDOS
;
DISKFUL2:
LXI D,DSKFMSG
CALL OUTPUT
;
NEWDISK:
CALL DISMOUNT ;dismount old disk
CALL MOUNT ;get new disk
JMP FORMFCB
;
TOOBIG:
LXI D,BIGMSG ;yes, 2nd floppy. send message
CALL STROUT ;warning that this file cannot
LXI D,PRNTREC
CALL STROUT ;print the file name also
JMP NEXTFILE
;
NOTFOUND:
LXI D,NFMSG
CALL OUTPUT
LXI D,PRNTREC
CALL OUTPUT
RET
;.....
;
DONE:
LXI D,DONEBU
JMP STROUT
;
DISMOUNT:
LXI D,DMNTMSG ;dismount floppy
CALL OUTPUT ;message to console
LDA LINECNT ;check for full page v1.2
DCR A ; v1.2
JZ TOPOFFORM ;page full v1.2
DCR A ; v1.2
JZ TOPOFFORM ; v1.2
DCR A ; v1.2
JZ TOPOFFORM ; v1.2
STA LINECNT ; v1.2
LXI D,CRLFLFLF ;page not full put some lines in v1.2
CALL LIST ;do it v1.2
RET
;
FINI:
LXI D,FINIMSG
CALL BCKMSG
CALL DISMOUNT
RET
;....
;
;
; assorted routines
;
STRIP: MOV A,M
ANI 7FH
MOV M,A
INX H
DCR B
JNZ STRIP
RET
;
KOUT:
PUSH B
PUSH D
PUSH H
LXI B,-10
LXI D,-1
;
KOUT2:
DAD B
INX D
JC KOUT2
LXI B,10
DAD B
XCHG
MOV A,H
ORA L
JZ KOUT3
PUSH H
LHLD KPTR
DCX H
SHLD KPTR
POP H
CALL KOUT
;
KOUT3:
MOV A,E
ADI '0'
LHLD KPTR
MOV M,A
INX H
SHLD KPTR
POP H
POP D
POP B
RET
;
BCKMSG:
CALL OUTPUT
LXI D,BCKUMSG
CALL STROUT
RET
;
PRINTFILE:
LXI D,PRNTREC
CALL LIST
LDA MAX2
DCR A
STA MAX2 ;entries per line counter
JNZ CONTL
LXI D,CRLF ;go to new line
CALL LIST
MVI A,RECLN2
STA MAX2
CALL MARGIN ;add left margin to paper v1.2
LDA LINECNT ;decrement line counter
DCR A ;do it
JZ NEWPAG1 ;page full, do top of form v1.2
STA LINECNT ;keep it
RET
;
CONTL:
LXI D,DISSEP
CALL LIST
RET
;.....
;
HEADING3:
CALL LINCNT4 ;update the line counter v1.2
CALL MARGIN ;put print margin in v1.2
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 ;print heading on printer
CALL LIST ;for files to be backed up
MVI A,RECLN2
STA MAX2
LXI D,CRLFLFLF ;add some blank lines v1.2
CALL LIST ;do it v1.2
JMP MARGIN
;
;.....
;
NEWPAG1:
CALL TOPOFFORM ; v1.2
JMP MARGIN ;put print margin in now v1.2
;
;.....
;
MOUNT:
LXI H,RAM
LDA LASTDSK
CMP M
JZ CONTM
;
MOV A,M
STA LASTDSK
LXI D,STRTMSG
CALL BCKMSG
JMP MOUNT2
;
CONTM:
LXI D,CONTMSG
CALL BCKMSG
;
MOUNT2:
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
CALL CLRSCRN
LXI D,BCKUM7
CALL OUTPUT
LXI D,VOLSER
CALL STROUT
LXI D,BCKUM8
CALL STROUT
MVI C,SYSRST ;do a system reset to change disks
CALL BDOS
LDA BACKUPDRV
SUI 41H
MOV E,A
MVI C,SELDSK
CALL BDOS
MVI C,GETDPB ;Get DPB
CALL BDOS
INX H
INX H
MOV A,M ;get block shift factor
SUI 3 ;-3 = kb shift factor
STA FLSFAC ;save it
LXI D,3
DAD D ;Get DSM
MOV E,M
INX H
MOV D,M
INX D
XCHG ;swap DE/HL
SHLD FLMAXS ;save it
DCX H
CALL DVHL8 ;DSM/8
INX H ;+1 = ALV SIZE
SHLD FLALVS ;save it
XCHG
INX H
INX H
MOV D,M
INX H
MOV E,M ;DE = AL0+AL1
MOV A,D ;Get # of bits
CALL BITS
MOV B,A
MOV A,E
CALL BITS
ADD B
STA FLDIRT ;save tot # of directory blocks
MVI A,0
STA FLDIRT+1
CALL SPACE
;
LHLD FLFREE
XCHG
LHLD FLMXKB
CALL SBHLDE
MOV A,H
ORA L
JNZ ERA
LXI D,EMPFL
CALL OUTPUT
JMP NOERA
;
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 A,0 ;start at user 0
NXTUSD:
MOV E,A
MVI C,SETUSR
PUSH PSW ;save user #
CALL BDOS ;set user
DELNFL: LXI D,FPFCB ; V1.1
LXI H,DUMMYFCB ; V1.1
MVI B,36 ; V1.1
CALL MOVE ; V1.1
MVI C,SRC1ST ;search for file V1.1
LXI D,FPFCB ; V1.1
CALL BDOS ; V1.1
CPI YES ; V1.1
JZ MORUSD ;done this user # V1.1
LXI H,FPFCB+1 ; V1.1
MVI B,11 ; V1.1
CALL STRIP ;clear attributes V1.1
MVI C,SETATT ; V1.1
LXI D,FPFCB ; V1.1
CALL BDOS ;remove them V1.1
MVI C,DELFIL ; V1.1
LXI D,FPFCB ; V1.1
CALL BDOS ;delete file on floppy V1.1
JMP DELNFL ;and look for next V1.1
MORUSD: POP PSW ;get user #
INR A ;next user
CPI 16 ;check if done (do 0-15)
JNZ NXTUSD ;delete all files in next user #
;
NOERA:
LXI D,CRLF
CALL STROUT
MVI E,0 ;back to user 0 for floppy
MVI C,SETUSR
CALL BDOS
CALL HEADING3 ;print heading on printer
CALL CLRFCB1 ;write labels on floppy
LDA DATE+6
STA FPFCB+2 ;convert MM/DD/YY date to
LDA DATE+7 ;YYMMDD
STA FPFCB+3
LDA DATE
STA FPFCB+4
LDA DATE+1
STA FPFCB+5 ;backup volume label is a 0k file of the
LDA DATE+3 ;format: "+yymmddh.vol"
STA FPFCB+6 ; where: yymmdd = iso format date of backup
LDA DATE+4 ; h = hard disk files are from
STA FPFCB+7 ; and vol = user-supplied volume id
LDA LASTDSK
STA FPFCB+8
CALL VOLABEL ;add extension to date v1.2
;
IF RBYANC ; add second file '--BACKUP.xxx' to output disk to be v1.2
; used by RBYANC. xxx= volser. Make's it easier to update v1.2
;since RBYANC cannot delete volumes, therefore old backup v1.2
;with only the date as volume label would remain in v1.2
; 'MAST.CAT',this format eliminates this problem v1.2
;
;
CALL CLRFCB1 ;clear the FCB v1.2
LXI H,BCKUPLBL ;find '--BACKUP' for second volume label v1.2
LXI D,FPFCB+1 ;move it to FCB v1.2
MVI B,8 ;move 8 characters v1.2
CALL MOVE
CALL VOLABEL ;make second file with format '-.vol' v1.2
ENDIF ; end RBYANC = YES v1.2
;
RET
;.....
;
CLRFCB1:
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
;
IF NOT RBYANC
MVI A,'-' ;add '-' to front of date file v1.2
ENDIF
;
IF RBYANC
MVI A,'+' ;RBYANC ... put '+' in front of date v1.2
ENDIF ;RBYANC v1.2
;
STA FPFCB+1 ;date file to avoid collision with YANC v1.2
RET
;
;.....
;
VOLABEL:
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,DELFIL ;delete file in case it exists
CALL BDOS ;already
LXI D,FPFCB
MVI C,MAKFIL ;create the file
CALL BDOS
INR A
JZ MOUNT ;disk full?
LXI D,FPFCB
MVI C,CLSFIL ;close the file
CALL BDOS
RET
;
;.....
;
SPACE: ;calculates space available
MVI C,GETALV ;Get Allocation Vector V1.1
CALL BDOS ; V1.1
SHLD FLALV ;and save it V1.1
LXI H,0
SHLD FLUSED ;clear used accumulator
LHLD FLALVS ;get allocation vector size
MOV B,H
MOV C,L
LHLD FLALV ;allocation vector address
ALVC:
MOV A,M ;get byte from ALV
CALL BITS ;count # of bits on
PUSH H ;save HL
MVI D,0
MOV E,A
LHLD FLUSED
DAD D
SHLD FLUSED ;add # of bits to total
POP H ;get HL again
INX H
DCR C ;decrement low byte of count
JNZ ALVC ;not done yet, keep counting
DCR B ;else decrement high byte
JP ALVC ;not done yet, continue
LHLD FLUSED
XCHG
LHLD FLMAXS
CALL SBHLDE ;MAX-USED=FREE
CALL SHIFT
SHLD FLFREE ;save FREE KB
LHLD FLDIRT
XCHG
LHLD FLMAXS ;get MAX
CALL SBHLDE ;MAX-DIR=MAX (actual)
CALL SHIFT ;convert to KB
SHLD FLMXKB ;save MAX KB
MVI H,BLANK ; V1.1
MVI L,BLANK ; V1.1
SHLD FREEKS ;clear space-string V1.1
SHLD FREEKS+2 ; V1.1
LXI H,FREEKS+3 ;load string-pointer V1.1
SHLD KPTR ; V1.1
LHLD FLFREE ;and number to convert V1.1
CALL KOUT ; V1.1
LXI D,FREEKS ;and print string V1.1
CALL STROUT ; V1.1
RET
;
SHIFT:
LDA FLSFAC ;get shift factor
FRS:
ORA A ;check shift factor
RZ ;if zero, done
PUSH PSW ;else save shift factor
MOV A,L
RAL ;shift low byte
MOV L,A
MOV A,H
RAL ;and high byte
MOV H,A
POP PSW
DCR A
JMP FRS
;....
;
DVHL8:
PUSH PSW
PUSH B
MVI B,3
DIVL:
MOV A,H
ORA A
RAR
MOV H,A
MOV A,L
RAR
MOV L,A
DCR B
JNZ DIVL
POP B
POP PSW
RET
;....
;
SBHLDE:
MOV A,L
SUB E
MOV L,A
MOV A,H
SBB D
MOV H,A
RET
;....
;
BITS:
CPI 0 ;if 0, zero bits
RZ ;return 0
CPI 0FFH ;if not 255
JNZ BITC ;must count the bits
MVI A,8 ;else, 8 bits
RET
BITC:
PUSH B ;save BC
MVI B,8 ;init count
MVI C,0 ;and accumulator
BITL:
RAL ;move bit to test it
JNC BITLC ;not on
INR C ;if on, increment count
BITLC:
DCR B ;decrement bit count
JNZ BITL ;if more to count, do it
MOV A,C ;else return # of bits
POP B ;restore BC
RET ;all done
;....
;
LOADBUFF:
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
;
LDA HDFCB ;get Hard disk drive
SUI 1 ;convert for BDOS
MOV E,A ;stick in E
MVI C,SELDSK ;call Select disk
CALL BDOS ;(for dumb systems w/o auto select)
;
LOADNEXT:
LHLD TEMP
XCHG ;set dma address
MVI C,SETDMA
CALL BDOS
LXI D,HDFCB ;read hard disk
MVI C,REDSEQ
CALL BDOS
ORA A
JNZ HDEOF ;eof?
LXI D,BCKUM5
CALL STROUT
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
JC HDRET ;return if memory already full
JMP LOADNEXT ;get another record
;
HDEOF: MVI A,1 ;set file eof
STA EOF
;
HDRET:
LDA FPFCB ;switch back to floppy drive
SUI 1 ;convert for BDOS
MOV E,A ;stick in E
MVI C,SELDSK ;call Select disk
CALL BDOS ;(for dumb systems w/o auto select)
RET
;.....
;
WRITEBUF:
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,SETDMA
CALL BDOS
LXI D,FPFCB
MVI C,WRTSEQ ;write sequential
CALL BDOS
ORA A
JNZ FPFULL ;floppy disk full
LXI D,BCKUM6
CALL STROUT
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:
MOV A,M ;get disk
STA PRNDISK
INX H ;point to user
MOV A,M
CALL CONVRT
MOV A,B
STA PRNUSR1
MOV A,C
STA PRNUSR2
INX H ;point to file name/type
LXI D,PRNFILE ;format the entry from the table
MVI B,8 ;format to the print format
CALL MOVE ;the table address is assummed to be
LXI D,8 ;in hl. first move the type
DAD D ;now position to the file type
LXI D,PRNTYPE ;move the file type
MVI B,3
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
CALL STROUT
POP D ;now put out the message
JMP STROUT ;print string pointed to by DE
;.....
;
TOPOFFORM: ; v1.2
LXI D,FRMFD ; v1.2
CALL LIST ; V1.2
MVI A,LINSPG ;find paper length v1.2
STA LINECNT ;reset line counter v1.2
RET
;
;.....
;
;
HEADING:
CALL MARGIN ;set printer margin v1.2
LXI D,HEAD1
CALL LIST
LXI D,DATE
CALL LIST
LXI D,TABFULL
LDA ABORT
ORA A
CNZ LIST
LDA RAM ;init LASTDSK for new page
STA LASTDSK
LDA RAM+1
STA LASTUSR ;init LASTUSR also
MVI A,RECLIN+1
STA MAX2
;
;.....
;
PAGECNT:
MVI A,LINSPG ;find the number lines per page v1.2
DCR A ;minus 6 to allow header spaces etc. v1.2
DCR A ; v1.2
DCR A ; v1.2
DCR A ; v1.2
DCR A ; v1.2
DCR A ; v1.2
STA LINECNT ;reset line counter v1.2
LXI D,CRLFLFLF ;put in some spaces after header v1.2
CALL LIST
CALL MARGIN
RET
;
;.....
;
LIST: PUSH H ;this differs from STROUT
PUSH B ; in that LIST goes to the
PUSH D ;list device and STROUT goes
;
LIST1: LDAX D ;to the console device
CPI 0
JZ LIST2
INX D
PUSH D
MOV E,A
MVI C,LSTOUT
CALL BDOS
POP D
JMP LIST1
LIST2 POP D
POP B
POP H
RET
;
STROUT: PUSH H ;this differs from LIST
PUSH B ; in that LIST goes to the
PUSH D ;list device and STROUT goes
;
STROT1: LDAX D ;to the console device
CPI 0
JZ STROT2
INX D
PUSH D
MOV E,A
MVI C,CONOUT
CALL BDOS
POP D
JMP STROT1
;
STROT2: POP D
POP B
POP H
RET
;.....
;
MARGIN: LXI D,IDENT ;find left margin value v1.2
CALL LIST ;print left margin v1.2
RET
;
;.....
;
LINCNT4:
LDA LINECNT ;find where it's at now v1.2
DCR A ;subtract for 4 LF's v1.2
JZ TOPOFFORM ;goto to new page v1.2
DCR A ;or subtract again v1.2
JZ TOPOFFORM ; v1.2
DCR A ; v1.2
JZ TOPOFFORM ; v1.2
DCR A ;must do this 4 times for the 3 LF's v1.2
JZ TOPOFFORM ; v1.2
STA LINECNT ;enough room on paper to start another v1.2
RET
;
;.....
;
QUESTION:
CALL OUTPUT ;put out the question
LXI D,INBUF
MVI C,INPSTR ;input the reply
CALL BDOS
LXI H,INBUF+2
LDA INCNT
ORA A
RZ ;if zero data, ret now
MOV B,A
CHKCAS:
MOV A,M
CPI 'a'
JC NXTC
CPI '{'
JNC NXTC
ANI 5FH
MOV M,A
NXTC:
INX H
DCR B
JNZ CHKCAS
;
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
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
;.....
;
;
;
;.....
;
;
IF CLOCK
GETDATE: ;put your GETDATE routine here
RET
;
ENDIF ;CLOCK
;
;
;....
;
CONVRT: MVI B,030H ;convert binary to decimal routine
MVI C,030H ;for nos from 0 to 99 b=tens,c=ones
;
CON1: SUI 10 ;a holds value to convert
JC CON2
INR B
JMP CON1
;
CON2: ADI 10 ;correct it
;
CON3: SUI 1
RC ;we are done
INR C ;do ones
JP CON3
;
DATETIME: DB ' 00/00/00 HH:MM:SS',0
;
DRIVES: DB 'ABC' ;drive nos for the hard disks
DB 0,0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0,0 ;end of list
;
BCKUPLBL: DB '--BACKUP',0
;
;
SIGNON: DB CR,LF,CR,LF
DB '>>> Backup Utility v1.2 Jan. 22, 1985',CR,LF
DB ' by Kim Levitt v1.0 Dec. 8, 1985',CR,LF
DB ' based on NEWBACK by G. Young',CR,LF
DB CR,LF
DB 0
;
IF RBYANC
SIGNON1: DB '>>> RBYANC compatible',CR,LF,0
ENDIF
;
IF PRNTSET
SIGNON2: DB '>>> DEC printers supported',CR,LF,0
ENDIF
;
DRIVMSG: DB 'Enter Letter of Drives to Backup from as '
DB '"A","B" or "AB": '
DB 0
;
BKUPMSG: DB 'Enter Letter of Floppy Drive to Backup to: '
DB 0
;
CORRMSG: DB CR,LF
DB ' >>> Backing up Drive(s): '
DB 0
;
CORRMSG1: DB ' to Floppy Drive: '
DB 0
;
CORRY$N: DB CR,LF
DB 'Is this Correct (Y/N)? '
DB 0
;
IF NOT CLOCK
DATEMSG: DB 'Enter 8 Char Date for Reports MM/DD/YY: '
DB 0
ENDIF ;NOT CLOCK
;
;
TAGMSG: DB 'Skip files that have been backed up? (F4 bit set) (Y/N)? ',0
;
SETF4Q: DB 'Set backup attribute bit (F4) after backup? (Y/N)? ',0
;
USRMSG: DB 'Backup all user areas (Y/N)? ',0
;
NOFILS: DB BEL,BEL,BEL,CR,LF,'NO files to backup found !!',0
;
SCANMSG: DB CR,LF,'Scanning directories...',CR,LF
;
DISKDIS: DB CR,' Disk: '
;
DISKID: DB '? User: ',0
;
USERDIS: DB BS,BS
;
USERID: DB '00',0
;
EMPFL: DB BEL,BEL,BEL,'Floppy Disk Empty, proceeding...',0
;
ERASE: DB BEL,BEL,BEL,'ERASE Floppy Disk First (Y/N)? ',0
;
TABFULL: DB BEL,BEL,BEL,'MEMORY FULL...BACKUP NOT COMPLETE',BEL,BEL,BEL,0
;
BACKQUS: DB CR,LF,'Begin Backup Procedure (Y/N)? ',0
;
SORTMSG: DB CR,LF,'Sorting...',0
;
NFMSG: DB BEL,BEL,BEL,'File not found... ABORTING',0
;
BCKUM: DB 'Backing up: ',0
;
BCKUM2: DB ' to: ',0
;
BCKUM3: DB ' ... ',0
;
BCKUM5: DB ' read ',BS,BS,BS,BS,BS,BS,0
;
BCKUM6: DB ' write',BS,BS,BS,BS,BS,BS,0
;
BCKUM7: DB CR,LF,'Beginning backup to volume: ',0
;
BCKUM8: DB ' ...',CR,LF,0
;
KILDUP: DB CR,LF,'Eliminating duplicate entries...',0
;
RPTING: DB CR,LF,'Writing consolidated listing...',0
;
FREEKS: DB ' K left',0
;
DONEBU: DB ' done.',0
;
DMNTMSG: DB BEL,BEL,BEL,BEL,BEL,'Please dismount backup disk and label: '
;
VOLSER: DB '???',0 ;VOLUME ID stored here
;
MNTMSG: DB BEL,BEL,BEL,'Mount backup disk on '
;
BACKUPDRV:DS 1 ;backup floppy drive letter
;
DB ' & enter 3 char disk ID or "END": ',0
;
ENDLIT: DB 'END'
;
PRNTREC:
PRNDISK: DS 1
PRNUSR1: DS 1
PRNUSR2: DS 1
DB ':'
PRNFILE: DS 8
DB '.'
PRNTYPE: DS 3
PRNTSIZ: DB ' ',0
PRNTK: DB 'k',0
DISSEP: DB ' ',0
;
CRLFLFLF: DB CR,LF,CR,LF,CR,LF,0
INDEX: DB 'The following files are on diskette No.: '
IDISKNO: DS 3
DB ' as of '
IDATE: DS 8
DB 0
;
CRLF: DB CR,LF,0
FRMFD: DB FF,0
;
;
IF COMPRES
TAB: DB ' ',0 ;tab 6 spaces between file names v1.2
IDENT: DB CR,' ',0 ;print left margin 9 spaces v1.2
ENDIF
;
IF NORMAL
TAB: DB '',0 ;tab 0 space between file names v1.2
IDENT: DB CR,' ',0 ;print left margin 5 spaces v1.2
ENDIF
;
HEAD1: DB 'Consolidated Alphabetical Index by disk/user as of ',0;
CURUSER: DB 16 ;current user number (local)
;
DATE: DS 8
DB ' ',0
;
BIGMSG: DB CR,LF,BEL,BEL,BEL,'File TOO large for one diskette '
DB 'so NOT backed up: ',0
;
DSKFMSG: DB CR,LF,BEL,BEL,BEL,'Floppy disk full.',CR,LF,0
;
STRTMSG: DB CR,LF,'Starting',0
;
CONTMSG: DB CR,LF,'Continuing',0
;
FINIMSG: DB CR,LF,'Finished',0
;
BCKUMSG: DB ' backup of disk: '
LASTDSK: DB '?.',CR,LF,0
;
EXITBU: DB CR,LF,'[Exiting BU]',CR,LF,0
;
SETF4: DB 0
;
KPTR: DW 0
;
HDFCB: DS 1
HDFILE: DS 8
HDTYPE: DS 3
DS 24
;
FPFCB: DS 36
;
INBUF: DB 30
INCNT: DS 1
INREC: DS 30
;
STACK: DS 80
;
EOF: DS 1
ABORT: DS 1
GOTONE: DS 1 ;flag to indicate valid file found, entry made
LINECNT: DS 1
LASTUSR: DS 1
TABADDR: DS 2
TABCNT: DS 2
SELFLAG: DS 1
ADDR1: DS 2
ADDR2: DS 2
ADDR3: DS 2
MAX1: DS 2
MAX2: DS 2
SAVCUSR: DS 2 ;used to restore max1 between users
TAGFLG: DB 'Y' ;set 'Y' or 'N' to indicate if tagged files skipped
CURUSR: DB 0 ;used to save current user on hard disk
FLFREE: DW 0 ;Floppy available space
FLMAXS: DW 0 ;Floppy maximum space
FLMXKB: DW 0 ;Floppy max in kb
FLUSED: DW 0 ;Floppy used space
FLALV: DW 0 ;allocation vector
FLALVS: DW 0 ;allocation vector size
FLDIRT: DW 0 ;directory total
FLSFAC: DB 0 ;shift factor
HDFLSZ: DW 0 ;Hard disk file size
;
RDISK: DS 1 ;disk ID
RUSR: DS 1 ;user #
RFILE: DS 8 ;filename
RTYPE: DS 3 ;and type
DB 0
;
TEMP: DS RECSIZ
DISKBUF: DS 128
COMPSIZE: DS 1
;
RAM: EQU $
;
END BASE+100H