; BIGBURST--BIG FILE BACKUP/RESTORE
; COPYRIGHT 1982, G. YOUNG, INC. 
; UPDATED 10/9/82
* 
* TO EXECUTE, ENTER THE PROGRAM NAME FOLLOWED BY THE FILE MASK:
*       A>BIGBURST FILENAME.TYP/B (FOR BACKUP) OR
*       A>BIGBURST FILENAME.TYP/R (FOR RESTORE)
* THE PURPOSE OF THIS PROGRAM IS TO BACKUP AND RESTORE FILES FROM/TO
* A HARD DISK WHERE THE FILE IS TOO BIG TO FIT ON ONE FLOPPY DISK.
* IT BACKS UP BY COPYING THE LARGE FILE TO MULTIPLE SMALL FILES
* WHICH WILL FIT ON THE FLOPPY.  THE FILE TYPE OF EACH OF THESE SMALL
* FILES IS A SEQUENTIAL NUMBER FROM 001 TO 255 WITH THE LAST RECORD
* ON THE LAST FILE CONTAINING AN INDICATOR THAT THIS IS THE LAST FILE.
* THE RESTORE PROCESS IS DONE BY COMBINING THESE SMALL FILES BACK INTO
* THE LARGE FILE.
* CHANGED 10/9/82 TO ASK QUESTIONS ON FLOPPY DRIVE #

* WRITTEN BY GARY YOUNG, BOX 3218, NO. HOLLYWOOD, CA 91609

	TITLE	'*** BIG FILE BACKUP/RESTORE ***'
BDOS	EQU	5
CR	EQU	0DH
LF	EQU	0AH
TBUF	EQU	80H
TFCB	EQU	5CH
BOOT	EQU	0
	ORG	100H
	JMP	START
	DB	'COPYRIGHT 1982, G. YOUNG, INC.'
START	LXI	SP,STACK+80
	LDA	TFCB+1		;SEE IF A MASK WAS ENTERED
	CPI	20H		;BUFFER WILL BE BLANK IF NOT
	JZ	INPUTERR
	LXI	H,TFCB		;SAVE THE INPUT FILE NAME
	LXI	D,HOLDFCB
	MVI	B,16
	CALL	MOVE
	LXI	D,HOLDFCB+16
	MVI	B,20
	CALL	CLEAR
	LXI	H,TBUF		;SEARCH FOR /B OR /R
	MVI	B,80
FINDSLSH MOV	A,M
	CPI	'/'
	JZ	BORR
	INX	H
	DCR	B
	JNZ	FINDSLSH
INPUTERR LXI	D,ERROR1
ERROR	CALL	OUTPUT
	JMP	BOOT
BORR	INX	H		;NEXT CHAR MUST BE A B OR R
	MOV	A,M
	CPI	'B'
	JZ	QUEST1
	CPI	'R'
	JNZ	INPUTERR
QUEST2	LXI	D,SRCFLPMSG
	CALL	QUESTION
	ORA	A
	JNZ	QUEST2A
	LDA	SRCFLP
	JMP	QUEST2B
QUEST2A LDA	INREC
QUEST2B	STA	FLOPPY
	JMP	RESTORE

QUEST1	LXI	D,DESTFLPMSG
	CALL	QUESTION
	ORA	A
	JNZ	QUEST1A
	LDA	DESTFLP
	JMP	QUEST1B
QUEST1A	LDA	INREC
QUEST1B	STA	FLOPPY
	JMP	BACKUP

RESTORE LXI	H,TFCB
	LXI	D,HDFCB
	MVI	B,12		;CREATE A HARD DISK FCB
	CALL	MOVE
	LXI	D,HDFCB+12
	MVI	B,24
	CALL	CLEAR
	LXI	H,0000
	SHLD	RECCNT
	XRA	A
	STA	FILECNT
	MVI	A,'$'		;CREATE A TEMPORARY FILE
	STA	HDFCB+9
	STA	HDFCB+10
	STA	HDFCB+11
	LXI	H,MSG3A		;MARK AS "RESTORE" IN MESSAGE
	LXI	D,MSG3
	MVI	B,8
	CALL	MOVE
	LXI	H,MSG0A
	LXI	D,MSG0		;CHANGE THE PROMPT MESSAGE
	MVI	B,10
	CALL	MOVE
	LXI	D,HDFCB		;SEE IF THE TEMP FILE IS THERE ON
	MVI	C,0FH		;THE HARD DISK
	CALL	BDOS
	INR	A
	JZ	MAKEHD
	LXI	D,HDFCB		;DELETE IT IF IT IS
	MVI	C,13H
	CALL	BDOS
MAKEHD	LXI	D,HDFCB		;MAKE THE HARD DISK FILE
	MVI	C,16H
	CALL	BDOS
	LXI	D,ERROR4	;ERROR IF DIRECTORY FULL
	INR	A
	JZ	ERROR
LOADFLP	CALL	GENFCB
LOAD2	CALL	MOUNT
	LXI	D,FLPFCB	;SEE IF FLOPPY FILE IS ON THAT DISK
	MVI	C,0FH
	CALL	BDOS
	INR	A
	JNZ	OPEN2		;YES, THE RIGHT ONE IS MOUNTED
	LXI	D,MESSAGE2	;NO, WRONG DISK IS MOUNTED
	CALL	OUTPUT
	JMP	LOAD2
OPEN2	LXI	D,HDFCB+12	;OPEN THE HARD DISK AGAIN
	MVI	B,24
	CALL	CLEAR
	LXI	D,HDFCB
	MVI	C,0FH
	CALL	BDOS
	LHLD	RECCNT		;POSITION TO END OF FILE
	SHLD	HDFCB+33
	LXI	D,HDFCB		;RANDOM READ
	MVI	C,21H
	CALL	BDOS
COPYLOOP2 CALL	LOADBUFF2	;ACTUAL COPY IS DONE HERE
	CALL	WRITEBUF2
	CALL	DEBUG
	LDA	EOF
	CPI	2
	JZ	ENDOFFILE2
	CPI	1
	JZ	DISKMPTY
	JMP	COPYLOOP2
ENDOFFILE2 LXI	D,HDFCB		;CLOSE HARD DISK
	MVI	C,10H
	CALL	BDOS
	LXI	D,HOLDFCB	;SEE IF THE FILE IS THERE
	MVI	C,0FH
	CALL	BDOS
	INR	A
	JZ	RENAME		;NO, RENAME THE TEMP VERSION AS THE FINAL NAME
	LXI	D,BAKFCB	;SEE IF THERE IS A BACKUP FILE NAME THERE
	MVI	B,36
	CALL	CLEAR
	LXI	H,HOLDFCB
	LXI	D,BAKFCB
	MVI	B,36
	CALL	MOVE
	LXI	H,BAK
	LXI	D,BAKFCB+9
	MVI	B,3
	CALL	MOVE		;CREATE THE BACKUP FILE NAME
	LXI	D,BAKFCB	;DELETE IT IF IT IS THERE
	MVI	C,13H
	CALL	BDOS
	LXI	H,BAKFCB
	LXI	D,HOLDFCB+16
	MVI	B,16
	CALL	MOVE
	LXI	D,HOLDFCB	;RENAME THE FINAL FILE NAME AS .BAK
	MVI	C,17H
	CALL	BDOS
RENAME	LXI	H,HOLDFCB
	LXI	D,HDFCB+16	;RENAME THE TEMP FILE TO THE PERMANENT NAME
	MVI	B,16
	CALL	MOVE
	LXI	D,HDFCB
	MVI	C,17H		;RENAME .$$$ AS .XXX (FINAL NAME)
	CALL	BDOS
	LXI	D,ERROR5	;FINISHED
	JMP	ERROR
DISKMPTY	LXI	D,FLPFCB	;CLOSE THE CURRENT FLOPPY FILE
	MVI	C,10H
	CALL	BDOS
	LXI	D,HDFCB		;CLOSE THE HARD DISK FILE ALSO, WILL OPEN
	MVI	C,10H		;AGAIN LATER, BUT MOUNTING THE NEW FLOPPY
	CALL	BDOS		;REQUIRES A RESET WHICH ASSUMES ALL CLOSED
	JMP	LOADFLP



BACKUP LXI	H,TFCB
	LXI	D,HDFCB
	MVI	B,12
	CALL	MOVE
	LXI	D,HDFCB+12
	MVI	B,24
	CALL	CLEAR
	LXI	H,0000
	SHLD	RECCNT
      	LXI	D,HDFCB		;MAKE SURE HARD DISK FILE IS THERE
	MVI	C,0FH
	CALL	BDOS
	INR	A
	JNZ	CLEARCNT
	LXI	D,ERROR2	;FILE NOT FOUND
	JMP	ERROR
CLEARCNT XRA	A
	STA	FILECNT
CREATEFLP CALL	GENFCB		;CREATE FLOPPY FCB
	CALL	MOUNT
      	LHLD	RECCNT		;POSITION FILE
	SHLD	HDFCB+33
	LXI	D,HDFCB		;RANDOM READ
	MVI	C,21H
	CALL	BDOS
	LXI	D,FLPFCB	;LOOK FOR FLOPPY NAME
	MVI	C,0FH
	CALL	BDOS
	INR	A
	JZ	MAKEFLOP
	LXI	D,FLPFCB	;DELETE IT IF IT IS THERE
	MVI	C,13H
	CALL	BDOS
MAKEFLOP LXI	D,FLPFCB	;CREATE THE FILE
	MVI	C,16H
	CALL	BDOS
	LXI	D,ERROR4
	INR	A
	JZ	ERROR		;DIRECTORY FULL
COPYLOOP1 CALL	LOADBUFF1	;DO ACTUAL COPYING HERE
	CALL	WRITEBUF1
	CALL	DEBUG
	LDA	EOF
	CPI	1
	JZ	ENDOFFILE1
	CPI	2
	JZ	DISKFULL
	JMP	COPYLOOP1
ENDOFFILE1	LXI	D,LASTREC	;ADD END OF ALL FILES RECORD
	MVI	C,1AH
	CALL	BDOS
	LXI	D,FLPFCB
	MVI	C,15H		;WRITE IT
	CALL	BDOS
	LXI	D,FLPFCB
	MVI	C,10H		;CLOSE FLOPPY
	CALL	BDOS
	LXI	D,ERROR5
	JMP	ERROR		;FINISHED
DISKFULL LXI	D,FLPFCB
	MVI	C,10H		;CLOSE FLOPPY
	CALL	BDOS
	JMP	CREATEFLP 

GENFCB	LXI	D,FLPFCB	;CREATE THE FLOPPY NAME
	MVI	B,36
	CALL	CLEAR
	LXI	H,HOLDFCB+1
	LXI	D,FLPFCB+1
	MVI	B,11
	CALL	MOVE
	LDA	FLOPPY
	ANI	0FH
	STA	FLPFCB
	LXI	D,ERROR3
	LDA	FILECNT
	INR	A
	STA	FILECNT
	JZ	ERROR		;TOO MANY FLOPPIES
	MVI	H,0
	MOV	L,A
	SHLD	MPTY
	LXI	D,FLPFCB+9	;SET FILE TYPE TO SEQUENCE NUMBER
	LXI	H,64H
	SHLD	TEMP2
	CALL	DIVID2
	LXI	H,0AH
	SHLD	TEMP2
	CALL	DIVID2
	LDA	MPTY
	ADI	'0'
	STAX	D
	RET

DEBUG	LHLD	RECCNT		;THIS PRINTS THE RECORD # JUST WRITTEN
	SHLD	MPTY		;FOR DEBUG PURPOSES
	LXI	D,DBMSG+2
	LXI	H,2710H
	SHLD	TEMP2
	CALL	DIVID2
	LXI	H,03E8H
	SHLD	TEMP2
	CALL	DIVID2
	LXI	H,64H
	SHLD	TEMP2
	CALL	DIVID2
	LXI	H,0AH
	SHLD	TEMP2
	CALL	DIVID2
	LDA	MPTY
	ADI	'0'
	STAX	D
	LXI	D,DBMSG
	CALL	OUTPUT
	RET

DIVID2	PUSH	D
	MVI	E,0
	LHLD	MPTY
	SHLD	TEMP
SB22	LXI	B,TEMP
	LXI	H,TEMP2
	XRA	A
	LDAX	B
	SBB	M
	STAX	B
	INX	B
	INX	H
	LDAX	B
	SBB	M
	STAX	B
	JC	NEG2
	INR	E
	PUSH	H
	LHLD	TEMP
	SHLD	MPTY
	POP	H
	JMP	SB22
NEG2	MOV	A,E
DIV2	ADI	'0'
	POP	D
	STAX	D
	INX	D
	RET

MOUNT	LXI	H,FLPFCB+1
	LXI	D,MSG1
	MVI	B,8
	CALL	MOVE
	LXI	D,MSG4
	CALL	MOVE
	LXI	H,FLPFCB+9
	LXI	D,MSG2
	MVI	B,3
	CALL	MOVE
	LXI	D,MSG5
	CALL	MOVE
	LXI	D,MESSAGE1
	CALL	OUTPUT
	LXI	D,INBUF
	MVI	C,0AH
	CALL	BDOS
	MVI	C,0DH		;RESET THE DISK SYSTEM
	CALL	BDOS
	RET

CLEAR	XRA	A
CLEAR2	STAX	D
	INX	D
	DCR	B
	JNZ	CLEAR2
	RET
 
;FOR BACKUP...LOAD FROM HARD DISK, WRITE TO FLOPPY
LOADBUFF1 EQU	$	;THIS ROUTINE LOADS AS MUCH OF
	LXI	H,0000		;MEMORY WITH THE FILE AS POSSIBLE
	SHLD	MAX1
	LXI	H,ADDR3
	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

WRITEBUF1 EQU	$	;WRITE FROM THE MEMORY BUFFER
	LXI	H,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,FLPFCB
	MVI	C,15H		;WRITE SEQUENTIAL
	CALL	BDOS
	ORA	A
	JNZ	FPFULL2
	LHLD	RECCNT
	INX	H
	SHLD	RECCNT
	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
FPFULL2	MVI	A,2		;FULL DISKETTE
	STA	EOF
	RET

;FOR RESTORE, LOAD FROM FLOPPY, WRITE TO HARD DISK
LOADBUFF2 EQU	$	;THIS ROUTINE LOADS AS MUCH OF
	LXI	H,0000		;MEMORY WITH THE FILE AS POSSIBLE
	SHLD	MAX1
	LXI	H,ADDR3
	SHLD	TEMP
	XRA	A
	STA	EOF		;CLEAR EOF FLAG
LOADNEXT2 LHLD	TEMP
	XCHG			;SET DMA ADDRESS
	MVI	C,1AH
	CALL	BDOS
	LXI	D,FLPFCB	;READ THE FLOPPY
	MVI	C,14H
	CALL	BDOS
	ORA	A
	JNZ	HDEOF2		;EOF?
	LHLD	TEMP
	LXI	D,LASTREC
	MVI	B,26		;SEE IF THIS IS THE LASTREC OF LAST FILE
	CALL	COMPARE
	JZ	EOFHD 
	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	LOADNEXT2	;GET ANOTHER RECORD
EOFHD	MVI	A,2
	STA	EOF
	RET
HDEOF2	MVI	A,1		;SET FILE EOF
	STA	EOF
	RET

WRITEBUF2 EQU	$	;WRITE FROM THE MEMORY BUFFER
	LXI	H,ADDR3
	SHLD	TEMP
	LHLD	MAX1		;ALLOW FOR FILES THAT HAVE NO 
	LXI	D,0000		;RECORDS SUCH AS RESTART
	CALL	COMPREG
	RZ
WRITENEXT2 LHLD	TEMP
	XCHG			;SET DMA ADDRESS
	MVI	C,1AH
	CALL	BDOS
	LXI	D,HDFCB
	MVI	C,15H		;WRITE SEQUENTIAL
	CALL	BDOS
	ORA	A
	JNZ	FPFULL		;FLOPPY DISK FULL
	LHLD	RECCNT
	INX	H
	SHLD	RECCNT
	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	WRITENEXT2
FPFULL	MVI	A,2		;FULL DISKETTE
	STA	EOF
	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
	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


CRLF	DB	CR,LF,'$'
ERROR1	DB	'INPUT ERROR...ENTER FILENAME.TYP/B OR /R',CR,LF,LF,'$'
ERROR2	DB	'FILE NOT FOUND',CR,LF,LF,'$'
ERROR3	DB	'NEEDS MORE THAN 255 FLOPPY DISKS',CR,LF,LF,'$'
ERROR4	DB	'DIRECTORY FULL',CR,LF,LF,'$'
ERROR5	DB	'FINISHED',CR,LF,LF,'$'
MSG0A	DB	'CONTAINING'
BAK	DB	'BAK'
MSG3A	DB	'RESTORE '
LASTREC	DB	'ENDENDENDBIGBURSTENDENDEND'
MESSAGE1 DB	CR,LF,LF,'MOUNT THE DISKETTE '
MSG0	DB	'TO CONTAIN '
MSG1	DS	8
	DB	'.'
MSG2	DS	3
	DB	' FOR '
MSG3	DB	'BACKUP  '
	DB	'AND HIT RETURN$'
MESSAGE2 DB	CR,LF,'FILE '
MSG4	DS	8
	DB	'.'
MSG5	DS	3
	DB	' IS NOT ON THIS DISKETTE$'
SRCFLPMSG DB	'SOURCE FLOPPY DRIVE (DEFAULT='
SRCFLP	DB	'D) $'
DESTFLPMSG DB	'DESTINATION FLOPPY DRIVE (DEFAULT='
DESTFLP	DB	'D) $'
DBMSG	DB	CR,LF
	DB	'00000$'
INBUF	DB	30
INCNT	DS	1
INREC	DS	30
FLOPPY	DS	1
RECCNT	DS	2
HOLDFCB	DS	36
HDFCB	DS	36
BAKFCB	DS	48
FILECNT	DS	1
FLPFCB	DS	36
TEMP	DS	2
TEMP2	DS	2
MPTY	DS	2
MAX1	DS	2
EOF	DS	1
STACK	DS	90
ADDR3	EQU	$
	END	100H
