	.title 'List and/or modify the Name/Password and defualt configuration Table'
	.sbttl 'USER'
version	==	1
revision==	0
	.pabs
	.phex
	.loc	100h
	jmp	START

; 		Program: USERTAB

; Read in, list, modify, and/or save 
; the Name/Password Table stored on
; track 3, sectors 1-32, and the default
; configuration table stored on all of
; tracks 4 and 5, of the Hard disk.

namebuf=	1000h	; loc for name and pass table
cofigbuf=	5000h	; loc for configuration table
mxdskTRK	=	10h
mxdskSEC	=	80h

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

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

;Temporary locations for Name/Password Table entries.
unit:	.byte	00h	; Hex byte (not in table)
TEMPentry:		;Beginning of table line
NAMaddr:.ascii	'        '	; 8 chr ascii string
PASaddr:.ascii	'      '	; 6 chr ascii string
control:.byte	00h		; Hex byte
size:	.byte	00h		; Hex byte

;Temporary locations for Default Table entries.
def1:	.ascii	'        '	; 8 chr ascii string
def2:	.ascii	'        '	; 8 chr ascii string
def3:	.ascii	'        '	; 8 chr ascii string
def4:	.ascii	'        '	; 8 chr ascii string
IOBYTE:	.byte	00h
	.ascii	'                                   '
	.ascii	'                                   '
	.ascii	'                                   '
	.ascii	'                                   '


; Step 1 - Read in name and password table, and the
;	   configuration table from the hard disk
;
; Step 2 - Print out current name/pass  map
;          Stop on special 'EOF' (name=0)
;
; 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
; Step 4 - Save as current name/pass map on hard disk
;
;---------
; MAIN BODY
;
START:
	lxi	sp,stack
	lxi	H,LOGmsg  ; print log-on message
	call	prtmsg
	call	chaMAPbyt ; assign unit 0 to hard disk
	mvi	A,32	  ; A = num of secs to read
	mvi	B,3	  ; B = starting track
	mvi	C,1	  ; C = starting sector
	lxi	H,namebuf ; HL= address of name table
	call	readTABL  ; read in name and pass table
	mvi	A,0FEh	  ; A = num of secs to read
	mvi	B,4	  ; B = starting track
	mvi	C,1	  ; C = starting sector
	lxi	H,cofigbuf; HL= address of config table
	call	readTABL  ; read in name and pass table
	call	resMAPbyt ; restore users unit 0 assmt
	lxi	H,HELPmsg ; print command summary
	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	'H'	 ; help listout requested?
	jrnz	Lcom
	lxi	H,helpmsg
	call	prtmsg
	jmpr	GETCOM

Lcom:	cpi	'L'	 ; print out name/pass  map?
	jrnz	Mcom
	call	prtTABL
	jmpr	GETCOM	 ; get next command

Mcom:	cpi	'M'	 ; modify name/pass  map?
	jnz	Qcom

; Get the entry number from the user.
getUNI:	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

; Get the name from the user.
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?
	jrc	..loadN	 ; Yes. Load the old name.
	cpi	1	 ; 1 chr long?
	jrnz	..1	 ; No. Load it in.
	push	H	 ; Save current table address
	lxi	H,conbuf+2 ; console buffer address
	mov	A,M	 ; Get the byte from conbuf
	pop	H	 ; Restore current table addr
	sui	'0'	 ; make ascii chr numeric
	cpi	0	 ; is it a zero (EOF)?
	jrnz	..1	 ; No. Its a name.
	lxi	H,NAMaddr; Yes. Put in a 0 in the table
	mvi	M,0	 ; Put a 0 into the Name addr &
	jmp	putTABL	 ; load it into the name table

..loadN:lda	unit
	mvi	B,16
	lxi	H,namebuf 
	call	ADDRfind
; HL = address of unit in namebuf  table.
	lxi	D,NAMaddr
	lxi	B,8
	ldir		; Copy old entry into Tempentry
	jmpr	getPAS

..1:	lxi	B,8	 ; BC = num of byte to transfer
	lxi	H,conbuf+2 ; HL = source address
	lxi	D,NAMaddr  ; DE = destination
	ldir		 ; load Name into temp addr

	lxi	H,NAMaddr
	mvi	B,8	 ; check 8 chrs for upper case
..2:	mov	A,M
	cpi	'a'	 ; is chr lower case?
	jrc	..3	 ; NO. check next letter
	ani	0DFh	 ; make it upper case
	mov	M,A	 ; and put it back
..3:	inx	H	 ; get next chr address
	dcr	B	 ; decrement the counter
	mov	A,B
	cpi	0	 ; all 8 chrs checked?
	jrnz	..2	 ; NO. Loop back 
			 ; Yes. Continue 

; Get the Password from the user
getPAS:	lxi	H,PASmsg ; whats the password?
	call	putBUF
	cpi	7	 ; more than 6 chrs long?
	cp	error
	jp	getPAS
	cpi	1	 ; Just a carriage return?
	jrc	..loadP	 ; Yes. Load the old entry
	lxi	B,6	 ; No. Load from console buffer
	lxi	H,conbuf+2
	lxi	D,PASaddr
	ldir		 ; load Password into temp addr
	jmpr	getD1	 ; and get the 1st default

..loadP:lda	unit
	mvi	B,16
	lxi	H,namebuf 
	call	ADDRfind
; HL = addr of unit in namebuf  table.
	lxi	D,8
	dad	D	; HL = addr of passwrd in table
	lxi	D,PASaddr ; DE = destination
	lxi	B,6	  ; BC = num of bytes to copy
	ldir		; Copy from namebuf  to temp

; Get the 1st default assignment from the user
getD1:	lxi	H,DEFmsg  ; Print default header
	call	prtmsg
	lxi	H,DEF1msg ; what's the name?
	call	putBUF
	cpi	9	 ; more than 8 chrs long?
	cp	error
	jp	getD1
	cpi	1	 ; less than 1 chr long?
	jrnc	..load1	 ; No. Its a name.
	lda	unit
	mvi	B,128
	lxi	H,cofigbuf
	call	ADDRfind
; HL = addr of entry in configuration table
	lxi	D,DEF1	 ; DE = destination
	lxi	B,8	 ; BC = num of bytes
	ldir		 ; Copy the bytes
	jmp	getD2	 ; and get the next name

..load1:lxi	H,conbuf+2 ; console buffer address
	lxi	B,8	 ; BC = num of byte to transfer
	lxi	H,conbuf+2 ; HL = source address
	lxi	D,DEF1	 ; DE = destination
	ldir		 ; load Name into temp addr

	lxi	H,DEF1
	mvi	B,8	 ; check 8 chrs for upper case
..2:	mov	A,M
	cpi	'a'	 ; is chr lower case?
	jrc	..3	 ; NO. check next letter
	ani	0DFh	 ; make it upper case
	mov	M,A	 ; and put it back
..3:	inx	H	 ; get next chr address
	dcr	B	 ; decrement the counter
	mov	A,B
	cpi	0	 ; all 8 chrs checked?
	jrnz	..2	 ; NO. Loop back 
			 ; Yes. Continue 

; Get the 2nd default assignment from the user
getD2:	lxi	H,crlf
	call	prtmsg
	lxi	H,DEF2msg ; what's the name?
	call	putBUF
	cpi	9	 ; more than 8 chrs long?
	cp	error
	jp	getD2
	cpi	1	 ; less than 1 chr long?
	jrnc	..load2	 ; No. Its a name.
	lda	unit
	mvi	B,128
	lxi	H,cofigbuf
	call	ADDRfind
	lxi	D,8
	dad	D
; HL = addr of entry in configuration table
	lxi	D,DEF2	 ; DE = destination
	lxi	B,8	 ; BC = num of bytes
	ldir		 ; Copy the bytes
	jmp	getD3	 ; and get the next name

..load2:lxi	H,conbuf+2 ; console buffer address
	lxi	B,8	 ; BC = num of byte to transfer
	lxi	H,conbuf+2 ; HL = source address
	lxi	D,DEF2	 ; DE = destination
	ldir		 ; load Name into temp addr

	lxi	H,DEF2
	mvi	B,8	 ; check 8 chrs for upper case
..4:	mov	A,M
	cpi	'a'	 ; is chr lower case?
	jrc	..5	 ; NO. check next letter
	ani	0DFh	 ; make it upper case
	mov	M,A	 ; and put it back
..5:	inx	H	 ; get next chr address
	dcr	B	 ; decrement the counter
	mov	A,B
	cpi	0	 ; all 8 chrs checked?
	jrnz	..4	 ; NO. Loop back 
			 ; Yes. Continue 

; Get the 3rd default assignment from the user
getD3:	lxi	H,crlf
	call	prtmsg
	lxi	H,DEF3msg ; what's the name?
	call	putBUF
	cpi	9	 ; more than 8 chrs long?
	cp	error
	jp	getD3
	cpi	1	 ; less than 1 chr long?
	jrnc	..load3	 ; No. Its a name.
	lda	unit
	mvi	B,128
	lxi	H,cofigbuf
	call	ADDRfind
	lxi	D,16
	dad	D
; HL = addr of entry in configuration table
	lxi	D,DEF3	 ; DE = destination
	lxi	B,8	 ; BC = num of bytes
	ldir		 ; Copy the bytes
	jmp	getD4	 ; and get the next name

..load3:lxi	H,conbuf+2 ; console buffer address
	lxi	B,8	 ; BC = num of byte to transfer
	lxi	H,conbuf+2 ; HL = source address
	lxi	D,DEF3	 ; DE = destination
	ldir		 ; load Name into temp addr

	lxi	H,DEF3
	mvi	B,8	 ; check 8 chrs for upper case
..6:	mov	A,M
	cpi	'a'	 ; is chr lower case?
	jrc	..7	 ; NO. check next letter
	ani	0DFh	 ; make it upper case
	mov	M,A	 ; and put it back
..7:	inx	H	 ; get next chr address
	dcr	B	 ; decrement the counter
	mov	A,B
	cpi	0	 ; all 8 chrs checked?
	jrnz	..6	 ; NO. Loop back 
			 ; Yes. Continue 

; Get the 4th default assignment from the user
getD4:	lxi	H,crlf
	call	prtmsg
	lxi	H,DEF4msg ; what's the name?
	call	putBUF
	cpi	9	 ; more than 8 chrs long?
	cp	error
	jp	getD4
	cpi	1	 ; less than 1 chr long?
	jrnc	..load4	 ; No. Its a name.
	lda	unit
	mvi	B,128
	lxi	H,cofigbuf
	call	ADDRfind
	lxi	D,24
	dad	D
; HL = addr of entry in configuration table
	lxi	D,DEF4	 ; DE = destination
	lxi	B,8	 ; BC = num of bytes
	ldir		 ; Copy the bytes
	jmp	getIOB	 ; and get the IOBYTE

..load4:lxi	H,conbuf+2 ; console buffer address
	lxi	B,8	 ; BC = num of byte to transfer
	lxi	H,conbuf+2 ; HL = source address
	lxi	D,DEF4	 ; DE = destination
	ldir		 ; load Name into temp addr

	lxi	H,DEF4
	mvi	B,8	 ; check 8 chrs for upper case
..8:	mov	A,M
	cpi	'a'	 ; is chr lower case?
	jrc	..9	 ; NO. check next letter
	ani	0DFh	 ; make it upper case
	mov	M,A	 ; and put it back
..9:	inx	H	 ; get next chr address
	dcr	B	 ; decrement the counter
	mov	A,B
	cpi	0	 ; all 8 chrs checked?
	jrnz	..8	 ; NO. Loop back 
			 ; Yes. Continue 

; Get the IObyte from the user.
getIOB:
	lxi	H,crlf
	call	prtmsg
	lxi	H,IOBmsg
	call	putBUF
	cpi	3	; longer than 3 characters?
	cp	error
	cp	getIOB
	cpi	0	; is buffer length 0
	jrnz	..10	; No. Make it a hex byte
	lda	unit	; Yes. Load the old IOBYTE
	mvi	B,128
	lxi	H,cofigbuf
	call	ADDRfind
	lxi	D,32
	dad	D
	mov	A,M
	jmpr	..11	
..10:	call	makHBYT
..11:	sta	IOBYTE

;----------
;Print out the header for the line, and print it.
	lxi	H,HEADmsg
	call	prtmsg
	lxi	H,TEMPentry	; addr of Temp line
	call	prtname		; print the Temp line
	lxi	H,def1
	call	prtCOF	 	; print default configs
;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	3	; 3 is Control-C
	jz	WBOOT	; Abort if Control-C
	cpi	'Y'
	cnz	error	; incorrect entry 
	jnz	ASKifOK
	lxi	H,crlf
	call	prtmsg	; space down a line
;now we figure out addr of line in table
putTABL:lda	unit	 ; A = unit num of addr needed
	mvi	B,16	 ; B = bytes per line of table
	lxi	H,namebuf; HL= addr of start of table
	call	ADDRfind ; get table addr of this unit
; HL = addr of this unit in name/password table
;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

	lda	unit
	lxi	H,cofigbuf
	mvi	B,128
	call	ADDRfind
; HL = addr of this unit in configuration table.
;now we copy 128 temp bytes into the table.
	lxi	B,128
	xchg
	lxi	H,def1
	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 ; Yes. Print 'Saving' message
	call	prtmsg
	call	chaMAPbyt; Assign hard disk to unit 0
	mvi	A,32	 ; A = num of sectors to write
	mvi	B,3	 ; B = starting track
	mvi	C,1	 ; C = starting sector
	lxi	H,namebuf; HL= address of name table
	call	writTABL ; write the D A T to disk
	mvi	A,0FEh
	mvi	B,4
	mvi	C,1
	lxi	H,cofigbuf
	call	writTABL
	call	resMAPbyt; restore users unit 0 assmt
	lxi	H,COMPmsg
	call	prtmsg	 ; tell user function completed

Zcom:	cpi	'Z'	 ; zero out name/pass  table?
	jrz	..clr	 ; Yes. 
	lxi	H,AIDmsg ; No. Bad entry.
	call	prtmsg	 ; Print ' H for help' msg
	jmp	GETCOM	 ; and get the next command
;BC=bytes to 0 out, HL=table addr
..clr:	lxi	B,16*64*32  ; length of table
	lxi	H,namebuf; 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 2-byte counter
	cpi	0
	jrnz	tablclr
	ora	B
	jrnz	tablclr
	lxi	H,COMPmsg
	call	prtmsg	 ; tell user function completed
	jmp	GETCOM	 ; get next command

;---------
;		Subroutine: prtTABL
; Regs  in:	none
; Regs out:	none
; Destroyed	A,H,L
;Print the disk name/pass and default configuration
;table halting if a name value of 0 is found. 

prtTABL:
	mvi	A,0
	sta	unit		; re-initialize 
	lxi	H,crlf
	call	prtmsg
	lxi	H,HEADmsg
	call	prtmsg		; print table header

..1:	lxi	H,namebuf
	mvi	B,16
	lda	unit
	call	ADDRfind
	call	prtname		; Print a line in name
	rc			; table. Return if crry
	lxi	H,cofigbuf
	mvi	B,128
	lda	unit
	call	ADDRfind
	call	prtcof
	lda	unit
	inr	A		; increment the line
	sta	unit
	cpi	0FFh
	jrnz	..1
	ret
;----------
;		Subroutine:	prtname
; Regs  in:	HL=addr in the name/pass  table
; Regs out:	HL=next addr in the name/pass  table
;Destroyed:	A,B,C
;Print one line in the table.
;Halt print out if a console chr is found.
;Resume print out when 2nd console chr is found.
prtname:
	push	H	; save name/pass  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 name/pass  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
	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
prtN:	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		; next addr in table
	inx	H		; next addr in table
	inx	H		; next addr in table
	ora	A		; clear A
	ret
;---------
; Subroutine: prtCOF
; Regs  in:
; Regs out:
; Destroyed:
; Print a line in the default configuration table
prtCOF:
	push	H
	lxi	H,def1msg
	call	prtmsg
	pop	H
	mvi	B,8
	call	prtchr
	push	H
	lxi	H,def2msg
	call	prtmsg
	pop	H
	inx	H
	mvi	B,8
	call	prtchr
	push	H
	lxi	H,def3msg
	call	prtmsg
	pop	H
	inx	H
	mvi	B,8
	call	prtchr
	push	H
	lxi	H,def4msg
	call	prtmsg
	pop	H
	inx	H
	mvi	B,8
	call	prtchr
	inx	H
	push	H
	mov	A,M
	push	PSW
	lxi	H,space4
	call	prtmsg
	pop	PSW
	call	prtbyt
	pop	H
	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 whose addr is needed
;	       B = Bytes per line of the table
;	       HL= addr of the start of the table
; Regs out:    HL= Addr of that line
;	          in the table 
;Destroyed:    A,B
;Find an addr of a line in a table
ADDRfind:
; A = line in table to find \  HL= start addr of table
	cpi	0	  ; first line of table?
	rz		  ; then were done
..1:	push	PSW	  ; save table line number
	mov	A,B	  ; incr table <Reg B> times 
..2:	inx	H
	dcr	A
	cpi	0	  ; Are we through this line?
	jrnz	..2	  ; No. continue incrementing
	pop	PSW	  ; Yes. Restore line counter
	dcr	A	  ; decr table line number
	cpi	0	  ; Are we all done?
	jrnz	..1	  ; No.incr to next line
	ret		  ; Yes. Return.
;---------
;		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
	call	CONOUT
	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:
	mov	C,A
	lxi	D,09h
	lixd	WBOOT+1
	dadx	D
	pcix
;----------
; Messages
LOGmsg:	.ascii	'USER  VER '
	.byte	version+'0','.'
	.byte	revision/10 + '0',revision@10+'0'
	.ascii	[cr][lf]'Name/Password/Configuration'
	.asciz	' Table Program'[cr][lf][lf]
COMmsg:	.asciz	[cr][lf][lf]' Command ?'
UNImsg:	.asciz	[cr][lf]'    Entry    (0,1,..63)?'
NAMmsg:	.asciz	[cr][lf]'    Name (up to 8 chrs)?'
PASmsg:	.asciz	[cr][lf]'Password (up to 6 chrs)?'
Defmsg:	.asciz	[cr][lf]'Defaults (up to 8 chrs)'
def1msg:.asciz	' A:'
def2msg:.asciz	' B:'
def3msg:.asciz	' C:'
def4msg:.asciz	' D:'
IOBmsg:	.asciz	' IObyte:'
AIDmsg:	.asciz	' Please type H for a command summary.'
Helpmsg:.ascii	[cr][lf]'  USER  Command Summary '
	.ascii	[cr][lf]'-----------------------'
	.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 '
	.ascii	'program without change'
	.ascii	[cr][lf]'S - Save as '
	.ascii	'the permanent table'
	.ascii	[cr][lf]'Z - Zero out the entire table'
	.ascii	[cr][lf]
	.ascii	[cr][lf]'Control-C aborts '
	.ascii	'program at any time'[cr][lf]
	.ascii	'To mark the end of the table, select '
	.ascii	'that entry (through the M function)'
	.ascii	[cr][lf]'and enter a 0 as its '
	.ascii	'Name.'[cr][lf]
	.ascii	'Also, just entering a carriage return'
	.ascii	' leaves that entry unchanged.'[lf]
crlf:	.asciz	[cr][lf]
HEADmsg:.ascii	[cr][lf]'Entry   Name  '
	.ascii	'   Password                   '
	.asciz	' Defaults                     IObyte'
VERIFYmsg:
	.asciz [cr][lf]'Is this listing correct? '
SAVmsg:	.ascii	[cr][lf]'WAIT - Saving Name/'
	.asciz	'Password/Configuration 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:


;*******************************************
;*                                         *
;* 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
curTRK:	.byte	00h	; current Track for disk I/O
curSEC:	.byte	00h	; current sector for disk I/O
numSEC:	.byte	00h	; num of sectors for disk I/O
;
;----------
;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
	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:
	call	CPMmap	; get current unit 0 assignment
;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
;----------
;Subroutine:	readTABL
; Regs  in:	 A= number of sectors to read
;	        HL= starting DMA address (table in mem)
;		 B= starting track
;		 C= starting sector
; Regs out:	none
;Destroyed:
readTABL:
	sta	numSEC	; save num of secs to read
	mov	A,B
	sta	curTRK	;set value for first track
	mov	A,C
	sta	curSEC	;set value for first sector
	shld	DMAaddr	;set value for first DMA addr
	ora	A	; reset the carry flag
..1:	rc		; return if carry bit set
	mvi	C,0
	call	SELDSK	; select hard disk
	lda	curTRK
	mov	C,A
	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:	 A= number of sectors to write
;	        HL= starting DMA address (table in mem)
;		 B= starting track
;		 C= starting sector
; Regs out:	none
;Destroyed:
writTABL:
	sta	numSEC	; save num of secs to read
	mov	A,B
	sta	curTRK	;set value for first track
	mov	A,C
	sta	curSEC	;set value for first sector
	shld	DMAaddr	;set value for first DMA addr
	ora	A	; reset the carry flag
..2:	rc
	
	mvi	C,0
	call	SELDSK	; select hard disk
	lda	curTRK
	mov	C,A
	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	..2	; read until INRaddr sets carry
;----------
;Subroutine:	INRdata
; Regs  in:	none
; Regs out:	carry bit is set/reset (used as a flag)
;Destroyed:
; Decrement the sector counter. Set carry flag if done
; Increment the DMA address and sector number
INRdata:

dcrSEC:	lda	numSEC	; number of SECs left to write
	dcr	A	; decrement,
	sta	numSEC	; and save.
	cpi	0	; Are we done writing sectors?
	jrnz	..3	; NO. Increment the data
	stc		; YES. Set the carry bit
	ret		; and return.

..3:	lhld	DMAaddr	; get current DMA address
	lxi	D,128
	dad	D	; increment by 128 bytes
	shld	DMAaddr	; and save as new DMA address

	lda	curSEC	; get the current sector
	inr	A	; increment,
	sta	curSEC	; and save as current sector
	cpi	mxdskSEC   ; past last sector?
	jrz	..4	   ; no, return
	jrc	..4	   ; no, return

	lda	curTRK	; get next track number
	cpi	mxdskTRK+1  ; past last track?
	jnc	error	; Yes. Terminal error. Abort.
	inr	A
	sta	curTRK
	mvi	A,1	; No. Reset sector number to 1
	sta	curSEC	; and save
..4:	ora	A	; reset carry flag
	ret		; and return.

;----------
; Call bios directly using WBaddr in low memory
WBaddr	=	WBOOT + 1

HOME:
	lhld	WBaddr
	lxi	D,15h
	dad	D
	pchl
	
SELDSK:
	lhld	WBaddr
	lxi	D,18h
	dad	D
	pchl

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:
	lhld	WBaddr
	lxi	D,60h
	dad	D
	pchl

SETBYT:
	lhld	WBaddr
	lxi	D,66h
	dad	D
	pchl

.end

