	.title	'Print the list of Hard Disk partitions'
	.sbttl	'DIRHARD'
version	==	1
revision==	1
        .pabs
	.phex
	.loc	100h
	sspd	saveSP
	lxi	SP,stack
	jmp	START
saveSP:	.word	0	; room for CCP's stack ptr
retCCP:
	lspd	saveSP
	ret
;----------
; This program tells the user the names of the hard
; disk partitions. The allocation table is read in
; directly from the hard disk to the userlist buffer.
; The partition names are then printed out in rows of
; three along with their respective sizes. The table
; we read in is then destroyed and we exit to the CCP.
;					D. Stein
;					11/20/80
WBOOT	=	00h	; Bios entry point location
WBaddr	=	01h     ; Warm boot location addr
userlist=	4000h	; addr of user table
usernum =	47h	; assigned user number loc
MAPbyt:	.byte	00h	; programs unit 0 assignment
curdrive=	04	; current drive number
cr	=	0Dh	; Ascii carriage return
lf	=	0Ah	; Ascii line feed
;
LOGmsg: .ascii	[cr][lf]' DIRHARD version '
	.byte	version+'0','.'
	.byte	revision/10+'0',revision@10+'0'
	.asciz	[cr][lf]
;----------
START:
; Print the log-on message
	lxi	H,LOGmsg
	call	prtmsg
; Initialize Direct Memory Address
	lxi	H,userlist
	shld	DMAaddr
; Load the proper MAPbyte for the hard disk.
	mvi	A,HDbyt	; get assignment byte for Hrd D
	sta	MAPbyt	; and save it as the MAP byte.
; Read in the partition table from the hard disk.
getTABL:
	call	chaMAPbyt ; assign unit 0 to MAPbyte
	mvi	A,8	  ; A = num of secs to read
	mvi	B,0	  ; B = starting track
	mvi	C,79h	  ; C = starting sector
	lxi	H,userlist; HL= address of name table
	call	readTABL  ; Read in name and pass table
	call	resMAPbyt ; Restore users original asmt
	jmp 	PRTTABL	  ; and print out the user list
	.page
;----------
; Routine: PRTTABL
;
; Print the userlist table.
; Print up to 16 lines, skipping any non-active users.
; Jump to the Console Command Processor when finished.
;
unit:	.byte	00h	; unit number of entry in table
size:	.byte	00h	; size of entry in stable
HEADmsg:.ascii	'                         '
	.ascii	' Current Hard Disk Partitions'
	.ascii	[cr][lf]'                         '
	.ascii	' ----------------------------'
crlf:	.asciz	[cr][lf]
space3:	.asciz	'   '
space6:	.asciz	'      '
msg256K:.asciz	'  256K bytes'
msg512K:.asciz	'  512K bytes'
msg1M:	.asciz	'    1M bytes'
msg2M:	.asciz	'    2M bytes'
msg4M:	.asciz	'    4M bytes'
msg8M:	.asciz	'    8M bytes'
Qmsg:	.asciz	'    ???     '
;
prtTABL:
	mvi	A,1
	sta	unit		; re-initialize 
	lxi	H,crlf
	call	prtmsg		; and space down.
	lxi	H,HEADmsg
	call	prtmsg		; print table header
;
..1:	lxi	H,userlist	; HL = addr of table
	mvi	B,16		; B = bytes per line
	lda	unit		; A = line to find
	call	ADDRfind	; HL returns with addr
	call	prtline		; Print a line in table
	jrc	exit		; Exit if prtline set
	lda	unit		; the carry bit.
	adi	3		; increment three lines
	sta	unit
	cpi	63		; 63 partitions checkd?
	jrc	..1		; No.  Loop back.
	lxi	H,crlf		; Yes.
	call	prtmsg		; space down a line
	lxi	H,crlf
	call	prtmsg		; space down a line
; All Disk partitions printed out. Destroy Alloc table
; at userlist. Exit to CCP.
exit:	lxi	H,userlist
	mvi	M,00
	lxi	D,userlist+1
	lxi	B,100h
	LDIR			; Destroy Alloc Table
	lxi	H,crlf
	call	prtmsg		; Space down a line and
	jmp	retCCP
	.page
;----------
; Subroutines for PRTTABL

;----------
;Subroutine:	prtline
; Regs  in:	HL=addr in the name/pass  table
; Regs out:	HL=next addr in the name/pass  table
;Destroyed:	A,B,C
;Used by prtname to print one line in the table.
;Halt print out if a console chr is found.
;Resume print out when 2nd console chr is found.
prtline:
	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 first byte in each line of the table.
; Halt print and return immediately if the size is 0.
;
;----------
; Check the first of three entries.
..4:	pop	H	; restore name/pass  tabl addr
	mov	A,M		; get the size
	sta	size		; store the size
	cpi	0		; Entry on this line?
	stc			; Set carry in case
	rz			; No. Return
;Table line is assumed ok.  Print it
	push	H
	lxi	H,crlf		; space down a line
	call	prtmsg
	lxi	H,space3
	call	prtmsg		; and space over 3.
	pop	H		; HL = size byte addr
	inx	H		; HL = 8 chr name addr
	mvi	B,8
	call	prtchr		; print 8 chr name
	call	prtSIZ		; print the size
;----------
; Check/Print the next entry
	lxi	D,8		; move to next line
	dad	D
	mov	A,M		; get size
	cpi	0		; Is it 0?
	stc			; Set carry in case
	rz			; Yes. Return
	inx	H		; No. Get to name addr
	sta	size		; and store the size
;Table line is assumed ok.  Print it
	push	H
	lxi	H,space6	; space over 4 spaces
	call	prtmsg
	pop	H
	mvi	B,8
	call	prtchr		; print 8 chr name
	call	prtSIZ
;----------
; Check/Print the next entry
	lxi	D,8
	dad	D
	mov	A,M		; get size
	cpi	0		; Is it 0?
	stc			; Set carry in case
	rz			; Yes. Return
	inx	H		; No. Get to name addr
	sta	size		; and store the size
;Table line is assumed ok.  Print it
	push	H
	lxi	H,space6	; space over 4 spaces
	call	prtmsg
	pop	H
	mvi	B,8
	call	prtchr		; print 8 chr name
	call	prtSIZ		; print the size
	inx	H		; No. Get to name addr
	ora	A		; No. Reset carry flag
	ret			; and return.
;---------
; Subroutine: prtSIZ
; Regs in:	none
; Regs out:	none
; Destroyed	A
;
; Print the size of the current entry in the table
prtSIZ:
	push	H		; save currnt tabl addr
	lda	size		; get the entry size
	lxi	H,msg256K
	cpi	1		; is size 1?
	cz	prtmsg		; Yes. Print 256K msg
	jrz	..return	; and return.
	lxi	H,msg512K
	cpi	2		; is size 2?
	cz	prtmsg		; Yes. Print 512K msg
	jrz	..return	; and return.
	lxi	H,msg1M
	cpi	3		; is size 3?
	cz	prtmsg		; Yes. Print 1 Meg msg
	jrz	..return	; and return.
	lxi	H,msg2M
	cpi	4		; is size 4?
	cz	prtmsg		; Yes. Print 2 Meg msg
	jrz	..return	; and return.
	lxi	H,msg4M
	cpi	5		; is size 5?
	cz	prtmsg		; Yes. Print 256K msg
	jrz	..return	; and return.
	lxi	H,msg8M
	cpi	6		; is size 6?
	cz	prtmsg		; Yes. Print 8 Meg msg
	jrz	..return	; and return.
	lxi	H,Qmsg		; No valid size found.
	call	prtmsg		; Print ??? msg,
..return:
	pop	H		; restore table address
	ret			; and return.
;---------
;		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.
;----------
; SUBROUTINES
;----------
; 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: prtchr
; Regs  in:	B =length of string
;		HL=addr of string
; Regs out:	HL=addr of last chr printed
;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	
;----------
; Print a byte on the console
;  Regs in:   A = byte to be printed
;  Regs out:  none
;  Destroyed: A
prtbyt:
	push	PSW
	rrc
	rrc
	rrc
	rrc
	ani	0Fh	; don't print leading zeros
	jrz	..1
	call	prtnbl
..1:	pop	PSW
prtnbl:	ani	0Fh
	adi	'0'
	cpi	'9'+1
	jrc	CONOUT
	adi	'A'-('9'+1)
	jmpr	CONOUT
;----------
; Convert binary to BCD
;  Regs in:   A = byte to be converted
;  Regs out:  A = byte, in BCD format
;  Destroyed: B
cvtbcd:
	ora	A
	rz
	mov	B,A
	xra	A
..1:	inr	A
	daa
	djnz	..1
	ret
;----------
; 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
;----------
;Subroutine: CONIN
; Fetch a character from the console.
CONIN:	lded	WBaddr
	lxi	H,06h
	dad	D
	pchl
;----------
;Subroutine: CONSTAT
; Regs  in:	none
; Regs out:	carry bit set if chr ready
; Destroyed:	
CONSTAT:
	lxi	H,..1
	push	H	; return to ..1
	lded	WBaddr
	lxi	H,03h
	dad	D
	pchl
..1:	rrc		; set parity bit if
	ret		;chr is ready.
;*******************************************
;*                                         *
;* NETWORK I/O DATA, DEFS, & SUBROUTINES   *
;*                                         *
;*******************************************
NETbyt	=	11000000b ; byte assigns hard disk to 0
HDbyt	=	10000000b ; byte assigns network to 0
mxdskTRK=	10h	; Max track number on hard disk
mxdskSEC=	80h	; Max sector number on h disk
tmpMAPbyt:
	.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 MAP byte.
; 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	tmpMAPbyt ; Save users assignment byte.
	lda	MAPbyt	; Get the assignment MAP byte.
	mov	M,A	; Assign the MAP byte.
	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 (network) returns in A
;BIOS address of the byte returns in HL
	lda	tmpMAPbyt  ; 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:	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.
;----------
ERROR:
	lxi	H,ERRmsg
	call	prtmsg
	jmp	0	; Abort due to terminal error
ERRmsg:	.ascii	[cr][lf]'NETWORK/HARD DISK error'
; 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

CPMMAP:
	lhld	WBaddr
	lxi	D,60h
	dad	D
	pchl

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

	.blkb	60	; room for stack
stack:	
.end

