;
;
; archive.asm utility version 1.0
;
;
TRUE	EQU	-1
FALSE	EQU	NOT TRUE
;
MPM	EQU	NOT TRUE
;
BDOS	EQU	5	;entry point to BDOS                    
EXIT	EQU	0	;CP/M exit point
DFCB	EQU	5CH	;Main file control block address        
FCBEXT	EQU	DFCB+12	;Extent byte of first file              
FCBRNO	EQU	DFCB+32	;Record number in first file            
DBUFF	EQU	80H	;default disk buffer
;
;CP/M Functions
;
CONINP	EQU	1	;Consol input to (A)                    
PCHAR	EQU	2	;Send char in (E) to con                
DIRCON	EQU	6	;Direct consol I/O (CP/M 2.2)           
PMESSG	EQU	9	;Print string pointed to by (DE)        
			;       end the string with '$'         
CONSTAT	EQU	11	;Get consol status                      
VERSION	EQU	12	;Get CP/M version number                
RSETDSK	EQU	13	;reset the disk (allow changing disks)  
SELDSK	EQU	14	;Log-in a new disk                      
OPEN	EQU	15	;Open a file, FCB in (DE)               
CLOSE	EQU	16	;Close a file, FCB in (DE)              
SRCHFST	EQU	17	;Search for first file, FCB in (DE)     
SRCHNXT	EQU	18	;Search for next file, FCB in (DE)      
DELETE	EQU	19	;Erase a file, FCB in (DE)              
READ	EQU	20	;Read a file sector, FCB in (DE)        
WRITE	EQU	21	;Write a file sector, FCB in (DE)       
MAKE	EQU	22	;Make a new file, FCB in (DE)           
CURRDSK	EQU	25	;Ask what current disk is               
STDMA	EQU	26	;Set the DMA (Disk I/O addr. (DE)       
ATTRIB	EQU	30	;Set the attributes of a file           
;
;Useful quates                                                               
;                                                               
CR	EQU	0DH	;ASCII carriage return character        
LF	EQU	0AH	;ASCII line feed character              
TAB	EQU	09H	;ASCII Tab-character
;
	org	100h
;
	jmp	over
;
	db	cr,lf,'ARCHIVE Ver.1.0, 6-Jun-82: Kelly Smith'
	db	cr,lf,'3055 Waco Avenue, Simi Valley, CA 93063'
	db	cr,lf,'Z'-40h
;
over:	lhld	bdos+1
	sphl
;
	mvi	c,currdsk
	call	bdos
	sta	logdsk
;
	mvi	c,rsetdsk
	call	bdos
;
	lda	logdsk
	mov	e,a
	mvi	c,seldsk
	call	bdos
;
	lxi	d,signon
	mvi	c,pmessg
	call	bdos
;
	mvi	c,version
	call	bdos
	cpi	022h
	lxi	d,bad$ver$num
	jnz	arcexit
;
	if	not mpm
	lhld	bdos+1
	lxi	d,05c9h
	dad	d
	shld	arch$addr
	mov	a,m
	cpi	0b8h
	jnz	patch$bdos
	lxi	d,noarch
	jmp	arcexit
;
patch$bdos:
;
	lhld	bdos+1
	lxi	d,03b2h
	dad	d
	xchg
	lhld	arch$addr
	mov	m,e
	inx	h
	mov	m,d
	endif
;
	lda	dfcb+1
	cpi	' '
	jnz	gotname
	lxi	d,no$file$nam
	mvi	c,pmessg
	call	bdos
	lxi	d,opts
	jmp	arcexit
;
gotname:
	lda	dfcb
	dcr	a
	mov	e,a
	mvi	c,seldsk
	inr	a
	sta	src$dsk$num
	cnz	bdos
	xra	a
	sta	dfcb
	mvi	a,'?'
	sta	dfcb+12
	lda	dfcb+17
	sta	option
	cpi	'B'
	jz	okopt
	cpi	'S'
	jz	okopt
	cpi	'R'
	jz	okopt
	cpi	'D'
	jz	okopt
;
badopt:
	lxi	d,ilgopt
arcexit:
	mvi	c,pmessg
	call	bdos
	jmp	exit
;
okopt:
	lda	option
	cpi	'B'
	jnz	arc$s$r
dest:	lxi	d,req$dest
	mvi	c,pmessg
	call	bdos
	mvi	c,coninp
	call	bdos
	ani	05fh
	sbi	'A'
	cpi	16
	jnc	dest
	lxi	h,logdsk
	ani	0fh
	cmp	m
	push	psw
	inr	a
	sta	dest$dsk$num
	pop	psw
	jz	dsksame
	inx	h
	mov	a,m
	inx	h
	cmp	m
	jnz	backup
dsksame:
	lxi	d,same$dsk
	mvi	c,pmessg
	call	bdos
	jmp	dest
;
arc$s$r:
	call	crlf
	xra	a
	sta	filcnt
	lxi	d,dfcb
	mvi	c,srchfst
	call	bdos
	inr	a
	jnz	gotfile
	lxi	d,no$file$fnd
	jmp	arcexit
;
gotfile:
	dcr	a
	rrc
	rrc
	rrc
	ani	60h
	lxi	h,dbuff
	mov	c,a
	mvi	b,0
	dad	b
	push	h
	lxi	b,filetable
	call	filepoint
	xchg
	lda	filcnt
	inr	a
	sta	filcnt
	pop	h
	mvi	b,32
	call	blkmov
getnext:
	mvi	c,srchnxt
	lxi	d,dfcb
	call	bdos
	inr	a
	jnz	gotfile
;
tagfile:
	call	abort
	lxi	b,filetable-32
	call	filepoint
	push	h
	lxi	d,dfcb
	mvi	b,32
	call	blkmov
	xra	a
	sta	dfcb
	lxi	d,-20
	dad	d
	mvi	m,'$'
	pop	d
	inx	d
	mvi	c,pmessg
	call	bdos
	mvi	e,' '
	mvi	c,pchar
	call	bdos
	lda	dfcb+12
	push	psw
	adi	'0'
	mov	e,a
	mvi	c,pchar
	pop	psw
	call	bdos
	lda	option
	cpi	'D'
	jz	nextfile
	rrc
	ani	80h
	mov	b,a
	lxi	d,dfcb+11
	ldax	d
	ani	7fh
	ora	b
	stax	d
	lxi	d,dfcb
	xra	a
	stax	d
	mvi	c,attrib
	call	bdos
;
nextfile:
	lda	dfcb+11
	rlc
	ani	1
	adi	'R'
	sta	donmsg+1
	lxi	d,donmsg
	mvi	c,pmessg
	call	bdos
	call	crlf
	lxi	h,filcnt
	dcr	m
	jz	exit
	jmp	tagfile
;
backup:	call	crlf
noback:	call	abort
	call	mfname
	jnc	movname
	lda	mfflgl
	ora	a
	lxi	d,bakup$done
	jnz	nofile
	lda	got$arc
	ora	a
	jnz	arcexit
	lxi	d,narcs
	jmp	arcexit
nofile:
	lxi	d,no$file$fnd
	jmp	arcexit
movname:
	lxi	h,dfcb+11
	mov	a,m
	rlc
	jc	noback
	rrc
	sta	got$arc
	ori	80h
	mov	m,a
	push	h
	lxi	d,dfcb
	mvi	c,attrib
	call	bdos
	pop	h
	dcx	h
	mov	a,m
	ani	07fh
	mov	m,a
	dcx	h
	mov	a,m
	ani	07fh
	mov	m,a
	lxi	h,dfcb+1
	lxi	d,fname
	mvi	b,8
	call	blkmov
	lxi	h,dfcb+9
	lxi	d,fname+9
	mvi	b,3
	call	blkmov
dspname:
	lxi	d,fname
	mvi	c,pmessg
	call	bdos
;
	mvi	b,11
	lxi	h,dfcb+1
	lxi	d,destfcb+1
	call	blkmov
;
	lda	logdsk
	mov	e,a
	mvi	c,seldsk
	call	bdos
	lxi	d,dfcb
	mvi	c,open
	call	bdos
	cpi	0ffh
	jnz	openok
	lxi	d,src$open$err
	jmp	arcexit
;
openok:
	lxi	d,destfcb
	lda	dest$dsk$num
	stax	d
	mvi	c,delete
	call	bdos
	lxi	d,destfcb
	mvi	c,make
	call	bdos
	cpi	0ffh
	jz	full
;
copy:
	lxi	h,(table$end-filetable)/128
	shld	bufmax
	xra	a
	sta	eof$flg
copy1:
	call	abort
	lxi	h,0
	shld	bufcnt
	lxi	h,filetable
	shld	bufpnt
;
copy2:
	lhld	bufpnt
	xchg
	mvi	c,stdma
	call	bdos
	lxi	d,dfcb
	mvi	c,read
	call	bdos
	ora	a
	jnz	copy3
	lhld	bufpnt
	lxi	d,128
	dad	d
	shld	bufpnt
	lhld	bufcnt
	inx	h
	shld	bufcnt
	xchg
	lhld	bufmax
	call	cdehl
	jnz	copy2
	jmp	copy4
;
copy3:
	mvi	a,0ffh
	sta	eof$flg
;
copy4:
	lxi	h,filetable
	shld	bufpnt
copy5:
	call	abort
	lhld	bufcnt
	mov	a,h
	ora	l
	jz	copy6
	dcx	h
	shld	bufcnt
	lhld	bufpnt
	push	h
	xchg
	mvi	c,stdma
	call	bdos
	pop	h
	lxi	d,128
	dad	d
	shld	bufpnt
	lxi	d,destfcb
	mvi	c,write
	call	bdos
	ora	a
	jz	copy5
	jmp	full
;
copy6:
	lda	eof$flg
	ora	a
	jz	copy1
	lxi	d,destfcb
	mvi	c,close
	call	bdos
	cpi	0ffh
	jnz	backup
	lxi	d,src$close$err
	jmp	arcexit
;
cdehl:
	mov	a,d
	cmp	h
	rnz
	mov	a,e
	cmp	l
	ret
;
full:
	lxi	d,destfcb
	mvi	c,delete
	call	bdos
	lxi	d,dsk$full
	mvi	c,pmessg
	call	bdos
	lda	dest$dsk$num
	adi	40h
	mov	e,a
	mvi	c,pchar
	call	bdos
	lxi	d,now$full
	mvi	c,pmessg
	call	bdos
req$cnt:
	lxi	d,enter$ret
	mvi	c,pmessg
	call	bdos
	mvi	c,coninp
	call	bdos
	cpi	cr
	jnz	req$cnt
	call	crlf
	mvi	c,rsetdsk
	call	bdos
	call	rset$fcb
	jmp	dspname
;
mfname:
	mvi	c,stdma
	lxi	d,dbuff
	call	bdos
	xra	a
	sta	fcbext
	sta	fcbrno
	lda	mfflgl
	ora	a
	jz	mfile1
	lxi	h,dfcb
	lxi	d,mfreq
	mvi	b,12
	call	blkmov
	lda	dfcb
	sta	mfcur
	lxi	h,mfreq
	lxi	d,dfcb
	mvi	b,12
	call	blkmov
	mvi	c,srchfst
	lxi	d,dfcb
	call	bdos
	jmp	mfile2
;
mfile1:
	lxi	h,mfcur
	lxi	d,dfcb
	mvi	b,12
	call	blkmov
	mvi	c,srchfst
	lxi	d,dfcb
	call	bdos
	lxi	h,mfreq
	lxi	d,dfcb
	mvi	b,12
	call	blkmov
	mvi	c,srchnxt
	lxi	d,dfcb
	call	bdos
mfile2:
	inr	a
	stc
	rz
;
	dcr	a
	ani	3
	add	a
	add	a
	add	a
	add	a
	add	a
	adi	81h
	mov	l,a
	mvi	h,0
	push	h
	lxi	d,mfcur+1
	mvi	b,11
	call	blkmov
;
	pop	h
	lxi	d,dfcb+1
	mvi	b,11
	call	blkmov
;
rset$fcb:
	lxi	d,dfcb
	lda	src$dsk$num
	stax	d
	xra	a
	sta	fcbext
	sta	fcbrno
	sta	destfcb
	sta	destfcb+12
	sta	destfcb+32
	sta	mfflgl
	ret
;
blkmov:
	mov	a,m
	stax	d
	inx	h
	inx	d
	dcr	b
	jnz	blkmov
	ret
;
filepoint:
	lhld	filcnt
	mvi	h,0
	dad	h
	dad	h
	dad	h
	dad	h
	dad	h
	dad	b
	ret
;
abort:
	push	h
	push	d
	push	b
	push	psw
	mvi	c,dircon
	mvi	e,0ffh
	call	bdos
	ora	a
	jz	abortx
	cpi	'C'-40h
	jnz	abortx
	lxi	d,abort$process
	mvi	c,pmessg
	call	bdos
	jmp	exit
abortx:
	pop	psw
	pop	b
	pop	d
	pop	h
	ret
;
crlf:
	lxi	d,crlf$msg
	mvi	c,pmessg
	call	bdos
	ret
;
signon:
	db	cr,lf,'ARCHIVE (CTRL-C f}r Abbruch) - Ver.1.0'
	db	cr,lf,cr,lf,'$'
;
ilgopt:
	db	'Invalid or Unspecified Option - Must Be pecified As:'
	db	cr,lf,cr,lf
opts:	db	tab,'B - Backup File Archive or,'
	db	cr,lf,tab,'S - Set File Archive or,'
	db	cr,lf,tab,'R - Reset File Archive or,'
	db	cr,lf,tab,'D - Display File Archive'
	db	cr,lf,'$'
no$file$fnd:
	db	cr,lf,'File Not Found, Aborting$'
;
donmsg:	db	'  ','$'
;
crlf$msg:
	db	cr,lf,'$'
;
bad$ver$num:
	db	'Must be CP/M Version 2.2 to Archive, Aborting$'
;
	if	not mpm
noarch:
	db	'Archiving Not Installed, Aborting$'
	endif
;
req$dest:
	db	'Destination Disk for BACKUP Files (A to P)? $'
;
same$dsk:
	db	cr,lf,'Can"t BACKUP to Source Disk You TWIT!',cr,lf,'$'
;
abort$process:
	db	cr,lf,'User Abort of ARCHIVE Process$'
;
narcs:	db	cr,lf,'No ARCHIVE Files Found to BACKUP$'
;
no$file$nam:
	db	'No Filename or Option Specified - '
	db	'ARCHIVE must be invoked as:'
	db	cr,lf,cr,lf
	db	tab,'ARCHIVE FN.FT OPTION<cr>'
	db	cr,lf,cr,lf
	db	'Where;',tab,'FN.FT is Filename and Filtype '
	db	'(? and * allowed)'
	db	cr,lf,cr,lf
	db	'And;',tab,'OPTION is specified as:'
	db	cr,lf,cr,lf,'$'
;
src$open$err:
	db	cr,lf,'Oops, Can"t Open File on Source Disk$'
;
dsk$full:
	db	cr,lf,'Destination BACKUP Disk $'
;
now$full:
	db	': is now FULL - Remove, insert NEW Disk$'
;
enter$ret:
	db	cr,lf,'Enter RETURN when ready to continue BACKUP process: $'
;
src$read$err:
	db	cr,lf,'Oops, Read Error on Source Disk$'
;
src$close$err:
	db	cr,lf,'Oops, Bad Close on Destination Disk$'
;
bakup$done:
	db	cr,lf,'BACKUP Complete',cr,lf,'$'
;
fname:
	db	'           $'
;
got$arc:
	db	0
mfflgl:
	db	1
mfreq:
	ds	12
mfcur:
	ds	12
arch$addr:
	ds	2
logdsk:
	ds	1
dest$dsk$num:
	ds	1
src$dsk$num:
	ds	1
filcnt:
	ds	1
option:
	ds	1
destfcb:
	ds	33
bufmax:
	ds	2
bufcnt:
	ds	2
bufpnt:
	ds	2
eof$flg:
	ds	1
filetable	equ	$
	ds	4*4096
table$end	equ	$
;
	end
