	.title 'List and/or modify the Disk Allocation Table'
	.sbttl 'ALLOC'
version	==	2
revision==	0
	.pabs
	.phex
	.loc	100h
	jmp	START

; 		Program: ALLOC

; Read in, list, modify, and/or save 
; the Disk Allocation Table (DAT) stored
; on the Network Hard Disk.

; Hard Disk I/O routines are at the end of the program

WBOOT	=	00h
BDOS	=	05h
wbadr	=	1	; vector for bios calls
cr	=	0Ah
lf	=	0Dh
conready=	0Bh	; for CP/M console status
bufread =	0Ah	; for CP/M console buffer reads

;Temporary locations for Disk Allocation Table Entries
unit:	.byte	00h	; Hex byte (not in table)
TEMPentry:		;Beginning of table line
size:	.byte	00h		; Hex byte
NAMaddr:.ascii	'        '	; 8 chr ascii string
PASaddr:.ascii	'      '	; 6 chr ascii string
control:.byte	00h		; Hex byte
;
; system type flag
; ffh is mpm, 0 is cpm1.4, else cpm2. version number
sysflg:	.byte	0

; Step 1 - Read in allocation map from hard disk
;
; Step 2 - Print out current allocation map
;          Stop on special 'EOF' (size=00)
;	   Print out 63rd table entry
; Step 3 - Get user commands
;		H - Help
;		M - Modify
;		Q - Quit the program safely
;		L - List out 'in mem' map
;		S - jump to Step 4
;		Z - Zero out current table in memory
;		E - ERASE CP/M DIRECTORY
; Step 4 - Save as current allocation map on hard disk
;
;---------
; MAIN BODY
;
START:
	lxi	sp,stack
	lhld	wbadr
	shld	WBaddr	; save for bios calls
	mvi	c,12	; get version function
	call	bdos
	mov	a,h	; see if mpm
	cpi	1
	mov	a,l	; use cpm indicator
	jnz	gotsys	; skip if not mpm
	mvi	a,0ffh	; mpm flag value
	lhld	WBaddr
	inx	h
	mov	e,m
	inx	h
	mov	d,m	; get real address
	sded	WBaddr
gotsys:	sta	sysflg	; save system type
	lxi	H,LOGmsg  ; print log-on message
	call	prtmsg
	call	getque	; grab disk if mpm
	call	chaMAPbyt ; assign unit 0 to hard disk
	call	readTABL  ; read in DAT from Hard disk
	call	resMAPbyt ; restore users unit 0 assmt
	call	putque	; free disk if mpm
	lxi	H,HELPmsg ; print command summary
	call	prtTABL   ; print allocation map
	lxi	H,crlf	  ; and space down
	call	prtmsg
;
; GET and interpret user COMmands
;
GETCOM:	
	lxi	H,COMmsg
	call	prtmsg	 ; tell user we are ready
wait:	call	CONSTAT
	jnc	wait	 ; wait for a user command

	call	CONIN	 ; read in the chr
	
	cpi	'E'	; erase dir wAnted ?
	jz	erase	; skip to it if so

	cpi	'H'	 ; help listout requested?
	jnz	Lcom
	lxi	H,helpmsg
	call	prtmsg
	jmp	GETCOM

;-----
; erase dir command
erase:	lda	sysflg
	ora	a
	jp	badcm	; error if not mpm
	lxi	h,dirbuf
	lxi	b,128
fill:	mvi	m,0e5h
	inx	h
	dcr	c
	jnz	fill	; initialize buffer
	call	getUNT	; get unit
	lxi	h,vermes
	call	prtmsg	; verify it
	call	conin
	cpi	'Y'
	jz	erok	; skip if good
badcm:	lxi	h,nvrmes
	call	prtmsg
	jmp	getcom
nvrmes:	.asciz	[cr][lf]' command aborted.'
vermes:	.ascii	[cr][lf]' type "Y" if you really'
	.asciz	' want to erase directory : '
erok:	call	conin	; force [cr] to be typed
	cpi	0dh
	jnz	badcm	; error if not
	call	getque	; enque if mpm
	mvi	c,0	; start at disk 0
	lda	unit
	ori	80h	;make hard disk
	sta	unit
	lxi	h,1	; drive vector
dsklp:	push	h	; save drive vector
	push	b	; save unit
	call	seldsk	; try to select
	pop	b	;restore unit
	mov	a,h
	ora	l
	jz	nodsk	; skip if bad select
	lxi	d,10
	dad	d	; skip to dpb pointer
	mov	e,m
	inx	h
	mov	d,m
	dcx	d	; point to unit byte
	ldax	d	; get unit
	lxi	h,unit
	cmp	m	; same ?
	jz	gotdsk	; skip if so
nodsk:	pop	h	; old drive vector
	dad	h	; next drive vector
	inr	c	; next disk
	mov	a,c
	cpi	16
	jnz	dsklp	; loop if more disks
	lxi	h,nota
	call	prtmsg	; tell disk not assigned
	jmp	getcom
nota:	.asciz	[cr][lf]' unit not assigned.'
gotdsk:	xchg		; unit addr to hl
	inx	h
	mov	a,m	; get sector/track
	inr	a	; make end + 1
	sta	spt
	lxi	d,7
	dad	d	; skip to #dir ents
	mov	e,m
	inx	h
	mov	d,m	; get # dir ents
	inx	d	; make true number
	sded	ndir
	lxi	d,5
	dad	d	; skip to # sys trk
	mov	e,m
	inx	h
	mov	d,m
	sded	trkad	; save as start track
	call	putque	; free disk
	pop	d	; get drive vector
	mvi	c,25h	; reset drive function
	call	bdos
	ora	a
	jz	dirlp	; skip if drive not busy
	lxi	h,bsymes
	call	prtmsg
	jmp	getcom	; reject command as drive busy
bsymes:	.asciz	[cr][lf]' rejected - unit is busy.'
;
; write out 'e5' to all directory blocks
;
dirlp:	call	getque	; freeze disk again
	lxi	b,dirbuf
	call	setDMA
nxtrk:	lbcd	trkad
	call	SETtrk
	mvi	a,1
	sta	wsec	; stArt sector
nxtsec:	mov	c,a
	mvi	b,0
	call	setSEC
	call	write
	lhld	ndir	; get # dir ents
	dcx	h
	dcx	h
	dcx	h
	dcx	h	; account for 4 ent/block
	shld	ndir	; save
	xra	a
	ora	h	; done ?
	jm	done	; skip if so
	jnz	mor	;skip if more
	ora	l
	jz	done	; skip if no more
mor:	lda	wsec
	inr	a
	sta	wsec
	lxi	h,spt
	cmp	m
	jnz	nxtsec
	lbcd	trkad
	inx	b	; next track
	sbcd	trkad
	jmpr	nxtrk
done:	call	putque	; free disk
	jmp	getcom	; next command
;
; erase data areas
;
spt:	.byte	0	; end of track sector number
ndir:	.word	0	; number of dirents
trkad:	.word	0	; track address save
wsec:	.byte	0	; running sector number
dirbuf:	.blkb	128	; hex 'e5' buffer
;-----
; get unit routine
getUNT:	lxi	H,UNImsg ; modify what unit number?
	call	putBUF
	cpi	3	 ; more than two chrs long?
	cp	error
	jp	getUNI
	cpi	1	 ; less than 1 chr long?
	cm	error
	jm	getUNI
	call	makDBYT	 ; make chrs into a byte
	cpi	64	 ; is UNIT more than 63?
	cp	error
	jp	getUNI
	sta	unit	 ; and save
	ret

Lcom:	cpi	'L'	 ; print out allocation map?
	jnz	Mcom
	call	prtTABL
	jmp	GETCOM	 ; get next command

Mcom:	cpi	'M'	 ; modify allocation map?
	jnz	Qcom

getUNI:	call	getUNT	; get unit

getSIZ:	lxi	H,SIZmsg ; what size?
	call	putBUF
	cpi	3	 ; buf more than two chrs?
	cp	error
	jp	getSIZ
	cpi	1	 ; buf less than 1 chr long?
	jrnc	..makSIZ ; No. Make chrs into a byte.
			 ; Yes. Fill in old size.
	lda	unit
	call	ADDRfind
; HL = address of unit in namebuf  table.
	lxi	D,size
	lxi	B,1
	ldir		; Copy old entry into Tempentry
	jmpr	getNAM

..makSIZ:
	call	makHBYT	 ; make chrs into a byte
	cpi	7	 ; is SIZE more than 6?
	cp	error
	jp	getSIZ
	sta	size	 ; save valid size value
	cpi	1	 ; size is 0? End of table mark
	jc	putTABL	 ; write immediately into table

getNAM:	lxi	H,NAMmsg ; what's the name?
	call	putBUF
	cpi	9	 ; more than 8 chrs long?
	cp	error
	jp	getNAM
	cpi	1	 ; less than 1 chr long?
	jrnc	..makNAM

	lda	unit
	call	ADDRfind
	inx	H
; HL = address of name in alloc  table.
	lxi	D,NAMaddr
	lxi	B,8
	ldir		; Copy old entry into Tempentry
	jmpr	getPAS	; and ask for the password.

..makNAM:
	lxi	B,8
	lxi	H,conbuf+2
	lxi	D,NAMaddr
	ldir		 ; load Name into temp addr

	lxi	H,NAMaddr
	mvi	B,8	 ; check 8 chrs for upper case
..1:	mov	A,M
	cpi	'a'	 ; is chr lower case?
	jc	..2	 ; NO. check next letter
	ani	0DFh	 ; make it upper case
	mov	M,A	 ; and put it back
..2:	inx	H	 ; get next chr address
	dcr	B	 ; decrement the counter
	mov	A,B
	cpi	0	 ; all 8 chrs checked?
	jrnz	..1	 ; NO. Loop back 
			 ; Yes. Continue 
getPAS:	lxi	H,PASmsg ; whats the password?
	call	putBUF
	cpi	7	 ; more than 6 chrs long?
	cp	error
	jp	getPAS
	cpi	1	 ; less than 1 chr long?
	jrnc	..makPAS ; No. Make buf into password
	
	lda	unit
	call	ADDRfind
	lxi	D,9
	dad	D
; HL = address of password in alloc  table.
	lxi	D,PASaddr
	lxi	B,6
	ldir		; Copy old entry into Tempentry
	jmpr	getCTL	; and ask for the password.

..makPAS:
	lxi	B,6
	lxi	H,conbuf+2
	lxi	D,PASaddr
	ldir		 ; load Password into temp addr

getCTL:	lxi	H,CTLmsg ; what's the Control value?
	call	putBUF
	cpi	3	 ; more than two chrs?
	cp	error
	jp	getCTL
	cpi	1	 ; Less than 1 chr long?
	jrnc	..makCTL ; No. make buf chrs into byte
	

	lda	unit
	call	ADDRfind
	lxi	D,15
	dad	D
; HL = address of password in alloc  table.
	lxi	D,control
	lxi	B,1
	ldir		; Copy old entry into Tempentry
	jmpr  ..prtHEAD ; and print out the line.

..makCTL:
	call	makHBYT	 ; make chrs into hex byte
	sta	control	 ; and save
;Print out the header for the line, and print it.
..prtHEAD:
	lxi	H,HEADmsg
	call	prtmsg
	lxi	H,TEMPentry	; addr of Temp line
	call	prtline		; print the Temp line
;Ask user if this listing is correct
ASKifOK:lxi	H,VERIFYmsg
	call	prtmsg
	call	CONIN	; get Y or N
	cpi	'N'
	jz	getCOM	; User wants to start over
	cpi	'Y'
	cnz	error	; incorrect entry 
	jnz	ASKifOK
;now we figure out addr of line in table
putTABL:lda	unit
	call	ADDRfind ; get table addr of this unit
;now we copy the 16 temp bytes into the table
	lxi	B,16	 ; bytes per line of table
	xchg		 ; get table destination in DE
	lxi	H,TEMPentry
	ldir		 ; put Temp line into table
;Notify user that function completed. Get next command.
	lxi	H,COMPmsg
	call	prtmsg	 ; tell user function completed
	jmp	getCOM	 ; get next user command

Qcom:	cpi	'Q'	 ; do we abort?
	jnz	Scom	 ; NO.
	jmp	WBOOT	 ; Yes.

Scom:	cpi	'S'	 ; do we save current allo-
			 ; cation table on hard disk?
	jnz	Zcom	 ; NO.
	lxi	H,SAVmsg
	call	prtmsg	 ; Yes. Print 'Saving' message
	call	getque	; enque disk if mpm
	call	chaMAPbyt; Assign hard disk to unit 0
	call	writTABL ; write the D A T to disk
	call	resMAPbyt; restore users unit 0 assmt
	call	putque	; free disk if mpm
; Delay approx 5 seconds so controller will flush
	mvi	A,00
..1:	push	PSW	
	lxi	H,0FFFFh ; count from FFFF down to 0000
..2:	dcx	H	 ; inner loop 
	mov	A,L	 
	cpi	0
	jrnz	..2
	ora	H
	jrnz	..2
	pop	PSW	 
	inr	A	 ; count from 0 to 11
	cpi	11	 ; outer loop
	jrc	..1
	out	00	 ; reset hard disk controler
	lxi	H,COMPmsg
	call	prtmsg	 ; tell user function completed

Zcom:	cpi	'Z'	 ; zero out allocation table?
	jnz	BADent	 ; Bad entry. Print help msg
;BC=bytes to 0 out, HL=table addr
	lxi	B,16*64  ; length of table
	lxi	H,tablbuf; addr of table
tablclr:mvi	M,0	 ; put a 0 into table
	inx	H	 ; next table addr
	dcx	B	 ; decrement the counter
	mov	A,C	 ; test the counter
	cpi	0
	jrnz	tablclr
	mov	A,B
	cpi	0
	jrnz	tablclr
	lxi	H,COMPmsg
	call	prtmsg	 ; tell user function completed
	jmp	GETCOM	 ; get next command

BADent:	lxi	H,AIDmsg
	call	prtmsg
	jmp	GETCOM	 ; Print help msg and loop back

;---------
;		Subroutine: prtTABL
; Regs  in:	none
; Regs out:	none
; Destroyed	A,H,L
;Print the disk allocation table halting if
;a size value of 0 is found. Print the 63rd
;listing always.
prtTABL:
	mvi	A,0
	sta	unit		; re-initialize 
	lxi	H,crlf
	call	prtmsg
	lxi	H,HEADmsg
	call	prtmsg		; print table header
	lxi	H,tablbuf
..1:	call	prtline		; print a table line
	jrc	..2		; print 63rd line if
				;STOPprt sets carry bit
	lda	unit
	inr	A		; increment the line
	sta	unit
	cpi	63
	jrnz	..1
..2:	mvi	A,63
	sta	unit
	call	ADDRfind
	call	prtline		; print 63rd listing
	ret
;----------
;		Subroutine:	prtline
; Regs  in:	HL=addr in the allocation table
; Regs out:	HL=next addr in the allocation table
;Destroyed:	A,B,C
;Print one line in the allocation table.
;Halt print out if a console chr is found.
;Resume print out when 2nd console chr is found.
prtline:
	push	H	; save allocation table address
	call	CONSTAT	; is console chr ready?
	jrnc	..4	; NO.
	call	CONIN	; eat the chr
..3:	call	CONSTAT ; is 2nd console chr ready?
	jrnc	..3	; wait for it
	call	CONIN	; eat the chr, and proceed

;Test the size (first entry in each line of the table)
;Halt print and return immediately if the size is 0.

..4:	pop	H	; restore allocation tabl addr
	mov	A,M		; get the size
	cpi	0		; End of Table?
	jz	STOPprt		; Yes. Gracefully Return
;Table line is assumed ok.  Print it
	push	H
	lxi	H,crlf		; space down a line
	call	prtmsg
	lxi	H,space4	; space over 4 spaces
	call	prtmsg	
	lda	unit		; unit number in A
prtUNI:	call	cvtbcd
	call	prtbyt		; print the unit number
	lxi	H,space4	; space over 4 spaces
	call	prtmsg
	pop	H
	mov	A,M		; get the size in A
	push	H
prtSIZ:	call	prtbyt		; print the size
	lxi	H,space4
	call	prtmsg		; space over 4 spaces
	pop	H
	inx	H		; get to name addr
prtNAM:	mvi	B,8
	call	prtchr		; print 8 chr name
	push	H
	lxi	H,space4	; space over 4 spaces
	call	prtmsg
	pop	H
	inx	H		; get to password addr
prtPAS:	mvi	B,6
	call	prtchr		; print 6 chr password
	push	H
	lxi	H,space4
	call	prtmsg
	pop	H
	inx	H		; get to control addr
prtCTL:	mov	A,M
	call	prtbyt
	inx	H		; next addr in table
	ora	A		; clear A
	ret

;----------
;		Subroutine: CONSTAT
; Regs  in:	none
; Regs out:	carry bit set if chr ready
; Destroyed:	
CONSTAT:
	mvi	C,conready
	call	BDOS
	rrc		; set parity bit if
	ret		;chr is ready.
;----------
;		Subroutine: putBUF
; Regs  in:	HL=address of message to print
; Regs out:	A =number of chrs put in buffer
;Destroyed:
;Put console input in a buffer
putBUF:
	call	prtmsg
	call	clrBUF	 ; clear the console buffer	
	mvi	C,bufread
	lxi	D,conbuf
	call	BDOS	 ; put console input in buffer
	lxi	H,conbuf+1
	mov	A,M	 ; put num of buffer chrs in A
	ret
;----------
;		Subroutine: clrBUF
; Regs  in:	none
; Regs out:
; Destroyed:
;Clear the console buffer
clrBUF:
	lxi	B,12
	lxi	H,clrBYTS
	lxi	D,conbuf+2
	ldir
	ret
;----------
;		Subroutine: makDBYT
; Regs  in:	A=length of console buffer
; Regs out:	A=decimal byte made from console buffer
;Destroyed:	HL,A,B,C
;Make a decimal byte from one or two buffer chrs
makDBYT:
	cpi	1	   ; just one chr
	mvi	B,0
	lxi	H,conbuf+2 ; load 1st chr addr
	jrz	..1
;multiply first chr by 10 and save
	mov	A,M
	sui	'0'	; make ascii chr numeric
	mov	B,A	; save original number
	rlc
	rlc
	rlc
	mov	C,A
	mov	A,B
	rlc
	add	C
	mov	B,A	;save 10*number in B
	inx	H	; get 2nd chr addr
..1:	mov	A,M
	sui	'0'	; make ascii chr numeric
	add	B	; add the two chrs
	ret
;----------

;----------
;		Subroutine: makHBYT
; Regs  in:	A=length of console buffer
; Regs out:	A=hex byte made from console buffer
;Destroyed:	HL,A,B,C
;Make a hex byte from one or two buffer chrs
makHBYT:
	cpi	1	   ; just one chr?
	mvi	B,0
	lxi	H,conbuf+2 ; load 1st chr addr
	jz	aa1	   ; process 1st chr only
;multiply first chr by 16 and save in B
	mov	A,M	; get 1st chr
	inx	H	; get to next chr
	cpi	'A'
	jm	aa2
	ani	0DFh	; make all letters upper case
	sui	'A'-'9'-1
aa2:	sui	'0'
	cpi	0
	jz	aa1	; skip mult if nibble is 0
	ora	A	; reset carry flag
	rlc
	rlc
	rlc
	rlc
	mov	B,A	;save 16*firstnumber in B
aa1:	mov	A,M	; get 2nd chr
	cpi	'A'
	jm	aa3
	ani	0DFh	; make all letters upper case
	sui	'A'-'9'-1
aa3:	sui	'0'
	ora	A	; reset the flags
	add	B	; add the two chrs
	ret

;---------
;		Subroutine: ADDRfind
; Regs  in:    A = A line in table that 
;		  an addr is needed for
; Regs out:    HL= Addr of that line
;	          in the table 
;Destroyed:    A,B
;Find an addr of a line in the table
ADDRfind:
	lxi	H,TABLbuf ; start addr of table
	cpi	0	  ; first line of table?
	rz		  ; then were done
..1:	push	PSW	  ; save table line number
	mvi	A,16	  ; incr table 16 times 
..2:	inx	H
	dcr	A
	cpi	0
	jrnz	..2
	pop	PSW
	dcr	A	  ; decr table line number
	cpi	0	  ; all done
	jrnz	..1	  ; incr to next line
	ret
;---------
;		Subroutine: STOPprt
; Regs  in:	none
; Regs out:	none
;Destroyed:	HL,A
;Gracefully abort from a subroutine and set carry bit
STOPprt:
	lxi	H,crlf	; space down a line
	call	prtmsg
	stc		; set the carry bit
	ret

;----------
;		Subroutine: cvtbcd
; Regs  in:	A=byte to be converted
; Regs out:	A=byte, in BCD format
; Destroyed:	B
;Convert binary to BCD
cvtbcd:
	ora	A
	rz
	mov	B,A
	xra	A
..1:	inr	A
	daa
	djnz	..1
	ret
;----------
;		Subroutine: CONIN
;Fetch a character from the console.
;Make all input letters UPPER CASE,
; and abort if chr is a ^C.
CONIN:	mvi	C,1
	call	BDOS
	cpi	3	;3 is ^C
	jz	WBOOT	;boot if ^C
	cpi	'a'
	rm
	cpi	'z'+1
	rp
	sui	'a'-'A'
	ret
;----------
;		Subroutine: prtbyt
; Regs  in:	A=byte to be printed
; Regs out:	none
; Destroyed:	A,B,C
;Print a byte on the console
prtbyt:
	push	PSW	; save the chr
	rlc
	rlc
	rlc
	rlc
	call	prtnbl
	pop	PSW
	call	prtnbl
	ret
prtnbl:	ani	0Fh
	adi	'0'
	cpi	'9'+1
	jc	CONOUT
	adi	'A'-('9'+1)
	jmp	CONOUT
;----------
;		Subroutine: prtchr
; Regs  in:	B =length of string
;		HL=addr of string
; Regs out:	none
;Destroyed:	B,A
;Print a specified number of chrs to the console
prtchr:
	mov	A,M
	push	B
	push	H
	call	CONOUT
	pop	H
	pop	B
	dcr	B
	mov	A,B
	cpi	0	; all B chrs printed?
	rz
	inx	H	; next chr addr
	jmpr	prtchr	
;----------
;		Subroutine: prtmsg
; Print a message on the console
;  Regs in:	HL = address of string (ended by null)
;  Regs out:	none
;  Destroyed:	A, HL
prtmsg:
	mov	A,M
	ora	A
	rz
	push	h
	call	CONOUT
	pop	h
	inx	H
	jmpr	prtmsg
;----------
;		Subroutine: Error
; Regs  in:	none
; Regs out:	none
;Destroyed:	HL
;Notifly operator that an incorrect entry has been made
ERROR:	
	push	PSW	; save status flag
	lxi	H,errmsg
	call	prtmsg
	pop	PSW
	ret
;----------
;		Subroutine: CONOUT
; Print a character on the console
;  Regs in:	A = character to be printed
;  Regs out:	none
;  Destroyed:	C
CONOUT:
	push	h
	push	d
	push	b
	mov	e,a
	mvi	c,2	; conout function
	call	bdos
	pop	b
	pop	d
	pop	h
	ret
;----------
; Messages
LOGmsg:	.ascii	'ALLOC VER '
	.byte	version+'0','.'
	.byte	revision/10 + '0',revision@10+'0'
	.ascii	[cr][lf]'Disk Allocation Table Program'
	.asciz	[cr][lf][lf]
COMmsg:	.asciz	[cr][lf][lf]' Command ?'
UNImsg:	.asciz	[cr][lf]'    Unit     (0,1,..63)?'
SIZmsg:	.asciz	[cr][lf]'    Size     (1,2,..6) ?'
NAMmsg:	.asciz	[cr][lf]'    Name (up to 8 chrs)?'
PASmsg:	.asciz	[cr][lf]'Password (up to 6 chrs)?'
CTLmsg:	.asciz	[cr][lf]' Control     (0,1,..FF)?'

Helpmsg:.ascii	[cr][lf][lf]
	.ascii	'         ALLOC Command Summary '
	.ascii	[cr][lf]
	.ascii	'        -----------------------'
	.ascii	[cr][lf]
	.ascii	[cr][lf]'H - Print this Help summary'
	.ascii	[cr][lf]'L - List out current table'
	.ascii	[cr][lf]'M - Modify an '
	.ascii	'entry in the table'
	.ascii	[cr][lf]'Q - Quit the program'
	.ascii	[cr][lf]'S - Save as '
	.ascii	'the permanent table'
	.ascii	[cr][lf]'Z - Zero out the entire table'
	.ascii	[cr][lf]'E - Erase directory on disk'
	.ascii	[cr][lf]
	.ascii	[cr][lf]'Control-C aborts '
	.ascii	'program at any time'
crlf:	.asciz	[cr][lf]
AIDmsg:	.asciz	'  Please type H for a command summary'
HEADmsg:.ascii	[cr][lf]'   Unit  Size     Name  '
	.asciz	'   Password  Ctrl'
VERIFYmsg:
	.asciz [cr][lf]'Is this listing correct? '
SAVmsg:	.ascii	[cr][lf]'WAIT - Saving '
	.asciz	'Disk Allocation Table '
COMPmsg:.asciz	[cr][lf]'Function Completed'
space4:	.asciz	'    '

errmsg:	.ascii	[cr][lf]' Incorrect entry. '
	.ascii  'Control-C aborts program.  '
	.asciz	'Please try again.'

conbuf:	.byte	12,0
	.byte	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
clrBYTS:.ascii	'                          '

	.blkb	100
stack:

tablbuf=1000h	; 1K Disk Allocation Table

;*******************************************
;*                                         *
;* HARD DISK I/O DATA, DEFS, & SUBROUTINES *
;*                                         *
;*******************************************

WBOOT	=	0
HDbyt	=	10000000b ; byte assigns hard disk to 0
MAPbyt:	.byte	00h	; users unit 0 assignment
DMAaddr:.word	00h	; current DMAaddr for disk I/O
cursec:	.byte	00h	; current sector for disk I/O
tablbuf=	1000h	; location for Disk Alloc Table
;
;----------
;Subroutine:	chaMAPbyt
; Regs  in:	none
; Regs out:	none
;Destroyed:	any and/or all registers

; Change the unit 0 assignment to that of a hard disk.
; Save the previous assignment for restoration.
chaMAPbyt:
	mvi	C,0
	call	SELDSK	; select unit 0 f
	call	CPMmap	; get current unit 0 assignment
; Current unit 0 assignment (network,etc) returns in A
; BIOS address of the byte returns in HL
	sta	MAPbyt	; save it for later restoration
	shld	mapres
	mvi	M,HDbyt	; assign unit 0 to a hard disk
	ret
;----------
;Subroutine:  resMAPbyt
; Regs  in:	none
; Regs out:	none
;Destroyed:	any and/or all registers

; Restore the previous unit 0 assignment
resMAPbyt:
	lhld	mapres
;Current unit 0 assignment (hard disk) returns in A
;BIOS address of the byte returns in HL
	lda	MAPbyt	; original unit 0 assignment
	mov	M,A	; restore previous assignment
	ret
mapres:	.word	0	; map byte address
;----------
;Subroutine:	readTABL
; Regs  in:	none
; Regs out:	none
;Destroyed:

; Read the D A T from the hard disk into the buffer
; Disk Allocation Table :
; Network Hard Disk Track 0, sectors 121-128
;Disk Allocation Table Buffer: 1000h (tablbuf)
readTABL:
	mvi	A,121
	sta	cursec	;set value for first sector
	lxi	H,tablbuf
	shld	DMAaddr	;set value for first DMA addr
	call	HOME
	ora	A	; reset the carry flag
..1:	rc		; return if carry bit set
	mvi	C,0
	call	SELDSK	; select hard disk
	mvi	C,0
	call	SETTRK	; select track 0
	lda	cursec	; load current sector
	mov	C,A
	call	SETSEC	; select current sector
	lbcd	DMAaddr
	call	SETDMA	; select proper buffer location
	call	READ	; and read from the disk
	call	INRdata	; increment DMA addr and sector
	jmpr	..1	; read until INRaddr sets carry
;----------
;Subroutine:	writTABL
; Regs  in:	none
; Regs out:	none
;Destroyed:

; Write the D A T from the buffer to the hard disk
; Disk Allocation Table:
; Network Hard Disk: Track 0, sectors 121-128
; Disk Allocation Table Buffer: 1000h (tablbuf)
writTABL:
	mvi	A,121
	sta	cursec	;set value for first sector
	lxi	H,tablbuf
	shld	DMAaddr	;set value for first DMA addr
	ora	A	; reset the carry flag
..1:	rc
	mvi	C,0
	call	SELDSK	; select hard disk
	mvi	C,0
	call	SETTRK	; select track 0
	lda	cursec	; load current sector
	mov	C,A
	call	SETSEC	; select current sector
	lbcd	DMAaddr
	call	SETDMA	; select proper buffer location
	call	WRITE	; and write to the disk
	call	INRdata	; increment DMA addr and sector
	jmpr	..1	; read until INRaddr sets carry
;----------
;Subroutine:	INRdata
; Regs  in:	none
; Regs out:	carry bit* (used as a flag)
;Destroyed:

; Increment the DMA address and sector number
; *Set the carry bit if last sector (128) has been read
INRdata:
	lhld	DMAaddr	; get current DMA address
	lxi	D,128
	dad	D	; increment by 128 bytes
	shld	DMAaddr	; and save it

	lda	cursec	; get the current sector
	inr	A
	sta	cursec
	cpi	129	; past 128th sector?
	jrnc	..1
	ora	A	; no. Resume reading or writing
	ret
..1:	stc		; set the carry flag
	ret		; and return

;----------
; Call bios directly using WBaddr in low memory
WBaddr:	.word	0	; for bios access

HOME:
	lhld	WBaddr
	lxi	D,15h
	dad	D
	pchl
	
SELDSK:
	lda	sysflg
	ora	a
	jp	notmpm	; skip if not mpm
	lxi	h,selret
	push	h	; return to us
notmpm:	lhld	WBaddr
	lxi	D,18h
	dad	D
	pchl
selret:	shld	mpmtab	; save dpb address
	ret
mpmtab:	.word	0

SETTRK:
	lhld	WBaddr
	lxi	D,1Bh
	dad	D
	pchl

SETSEC:
	lhld	WBaddr
	lxi	D,1Eh
	dad	D
	pchl

SETDMA:
	lhld	WBaddr
	lxi	D,21h
	dad	D
	pchl

READ:
	lhld	WBaddr
	lxi	D,24h
	dad	D
	pchl

WRITE:
	lhld	WBaddr
	lxi	D,27h
	dad	D
	pchl

CPMMAP:
	lda	sysflg
	ora	a
	jm	mpmmap	; skip if mpm
	lhld	WBaddr
	lxi	D,60h
	dad	D
	pchl
mpmmap:	lhld	mpmtab	; dpb address
	lxi	d,10	; offset to parm tab addr
	dad	d
	mov	e,m
	inx	h
	mov	d,m
	dcx	d	; unit + devtype byte
	xchg		; into hl
	mov	a,m	; get unit+devtype
	ret

SETBYT:
	lhld	WBaddr
	lxi	D,66h
	dad	D
	pchl
;
; getque - get disk mutual exclusion que if mpm
;
getque:	lda	sysflg
	ora	a
	rp		; return if cpm
	mvi	c,87h	; open que
	lxi	d,mpmq
	call	bdos
	mvi	c,89h	; read que
	lxi	d,mpmq
	call	bdos
	mvi	a,0ffh
	sta	queflg	; indicate que got
	ret
queflg:	.byte	0	; 0ffh if disk que got
mpmq:	.byte	0,0
	.word	qbuff
	.ascii	'MXDisk  ' ; disk q name
qbuff:	.byte	0,0	; q message
;
; putque - free disk que if got
;
putque:	lda	queflg
	ora	a
	rz		; exit if don't have que
	xra	a
	sta	queflg	; reset flag
	mvi	c,8bh	; write que function
	lxi	d,mpmq
	call	bdos
	ret

.end

