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

; 		Program: ALLOC

; Read in, list, modify, and/or save 
;the Disk Allocation Table (DAT) stored
;on the HiNet or stand-alone Hard Disk.
;The DAT is used to allocate user-selected
;names to hard disk partitions. A partition
;acts as a CP/M logical drive (A,B,C, or D). 
;			David Stein 10/80
; Update history

;	Version  1.02 -	Delete command added
;			Delete warning messages
;			added. Size change
;			routine now issues
;			warning messages, too.
;			ESCAPE to 'command?' prompt
;			added.
;	Version	 2.00 - Amount of space allocated
;			is now printed out after
;			each list (Lcom) is made.
;       Version  4.00   Locked partition 0(system) so
;                       as to prevent modification.
; 	Version  4.01   Works with MPM again
;
;Basic data definitions and jump/call locations
WBOOT	=	00h
BDOS	=	05h
wbadr	=	1	; vector for bios calls
cr	=	0Ah	; ascii non-printing commands
lf	=	0Dh
bell	=	07h
tb	=	09h
conready=	0Bh	; for CP/M console status
bufread =	0Ah	; for CP/M console buffer reads
.page
Š; Disk Allocation Table description
;
;16byte x 64 line Disk Allocation Table at 2000h
; The current table will be read in from track 0 sec- 
;tor 79 of the HiNet master or stand-alone hard disk.
;
; Label:      size  partition-name- -password--  ctrl
; byte count:  0    1,2,3,4,5,6,7,8 9,a,b,c,d,e   f
;
; The size byte can be from 1 to 6. A zero size byte
;signifies the end of the table.
; The name is eight upper case characters (blanks incl)
; The password is 6 upper or lower case characters with
;blanks also included.
; The control (ctrl) byte is any hex value and is not
;used at this time.
tablbuf	=	2000h

;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

; Hard Disk I/O routines are at the end of the program.
; Hard disk size identification table
HDsiztbl:
;    secs/trk   heads   num of tracks   disk size (Meg)
.byte	11,	  4,	    241,	   10
.byte	11,	  8,	    241,	   23
.byte	17,	  4,	    199,	   14
.byte	17,	  8,	    199,	   28  
.byte	00h	; End of table marker

;Used for disk space computation (ADDSIZ,PRTSPACE)
allospa:.byte	00
	.word	0000	; allocated disk space (in BCD)
usedspa:.word	0000h	;Sum of sizes (in K)
SPAmsg:	.asciz	[cr][lf]'Allocated disk space: '
endmsg:	.asciz	' Kbytes '

;System identification
; system type flag
; ffh is mpm, 0 is cpm1.4, else cpm2. version number
sysflg:	.byte	0
.page
Š; Step 1 - Read in allocation map from hard disk
;(not yet) Calculate size of hard disk
;
; Step 2 - Get user commands
;		A - Add an entry
;		D - Delete an entry
;		E - ERASE CP/M DIRECTORY
;		H - Help
;		M - Modify
;		Q - Quit the program safely
;		L - List out 'in mem' map
;		    and space allocated on disk
;		S - jump to Step 4
;		Z - Zero out current table in memory
; Step 3 - Save as current allocation map on hard disk
;
;---------
; MAIN BODY
;
TEST:
	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
	sta	sysflg
	jnz	gotsys	; skip if not mpm
	mvi	a,0ffh	; mpm flag value
	sta	sysflg
	lhld	WBaddr
	inx	h
	mov	e,m
	inx	h
	mov	d,m	; get real address
	sded	WBaddr
	jmp	START
;
; Don't run if not master or single user system
gotsys:
	lda	47h	  ; A = network user code
	cpi	0FFh	  ; FF= hard disk (no HiNet)
	jrz	START	  ; WE can proceed if Hard disk
	cpi	00h	  ; 00= network master
	jrz	START	  ; We can proceed if Network
	lxi	H,NOGOmsg ; This user is not legitimate
	call	prtmsg	  ; Give him the ax
	jmp	WBOOT	  ; and the boot.

	;User is AOK we can start.  Set the stack and
	;initialize for the Hard disk/Network reads
	;and writes.	
START:
	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	prtmsg
	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
	jrnc	wait	 ; wait for a user command

	call	CONIN	 ; read in the chr
	
	cpi	'A'	 ; add a new entry?
	jz	Acom
	cpi	'D'	 ; delete an entry?
	jz	Dcom
	cpi	'E'	 ; erase dir wanted ?
	jz	erase	 ; 
	cpi	'H'	 ; help listout requested?
	jz	Hcom
	cpi	'L'	 ; print out allocation map?
	jz	Lcom
	cpi	'M'	 ; modify allocation map?
	jz	Mcom
	cpi	'Q'	 ; do we abort?
	jz	Qcom	 
	cpi	'S'	 ; Do we save current allo-
	jz	Scom	 ; cation table on hard disk?
	cpi	'Z'	 ; zero out allocation table?
	jz	Zcom	
	lxi	H,AIDmsg ; Bad entry. Print help msg
	call	prtmsg
	jmp	GETCOM	 ; and ask again

;-----
; erase directory 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

Hcom:	lxi	H,helpmsg; Print help msg
	call	prtmsg
	jmp	GETCOM

Lcom:	call	prtTABL
	call	prtSPACE
	jmp	GETCOM	 ; get next command
.page
Š;----------
; Acom - ADD A NEW ENTRY TO THE TABLES.
;	 INITIALIZE THE NEXT OPEN SPOT IN THE TABLES
;	 AND JUMP INTO THE 'MODIFY' SECTION WHICH
;	 FOLLOWS THIS Acom SECTON.
;

Acom:			 ; Add a new entry into table

	mvi	A,0	 ; start at 1stline in table
..SRCH:	push	PSW	 ; A=table line number
	call	ADDRfind ; sent: A=table line number
			 ; 	 B=bytes per table line
			 ;	HL=start addr of table
			 ; ret:	HL=strt addr of line
	mov	A,M	 ; get 1st byte of that line
	cpi	0	 ; IS IT 0? 0 means its free.
	jrz	..found	 ; YES. Opening in table found.
	pop	PSW	 ; NO. Retreive table line num
	inr	A	 ; and set it to the next line.
	cpi	64	 ; HAVE WE checked all 63 lines
	jrc	..SRCH	 ; NO.  Loop and try next line.

	;Table is filled (63 entries).Tell user no room
	lxi	H,tblfulmsg ;YES. Load `table full` msg
	call	prtmsg	 ; and print it.
	jmp	GETCOM	 ; Get next user command.
	
; Unused line found. Now leave the first character as a
; 0 (that keeps this an unused line for the time being)
; and the next 13 characters (the rest of the name and
; password space) of that entry in name/pass table
; with blanks (ascii 20).  

..found:;Unused table line number is on TOP of STACK
	pop	PSW	; Restore line number
	sta	unit	; and save it.

	;HL=starting address of line of the name table
	inx	H	; Leave the 1st byte a 0
	mov	D,H
	mov	E,L
	inx	D	; DE = HL + 1
	mvi	M,' '	; Put in a blank
	lxi	B,13	; Blank out 13 characters
	LDIR

; Tell user what line in table has been selected.
; Jump to getNAM in Mcom (table line modification
; routine) to get the name, password, default con-
; figurations, and preset type-ahead buffer from
; the user.

	lxi	H,addmsg ; `Table line number is` msg
	call	prtmsg	 ; Print msg.
	lda	unit	 ; Get the table line number
	call	cvtbcd	 ; Make line number decimal
Š	call	prtbyt	 ; and print it.
	JMP	getSIZ	 ; Only operator input is now
			 ; needed.  getNAM is in Mcom
			 ; (modify command) and will
			 ; get all the needed data.
.page
Š;-----------
; Mcom - Modify an existing entry in the table
;
Mcom:
getUNI:	call	getUNT	; get unit

; Check that the entry is in use and can be modified.
; We do this by checking the first byte of that entry.
; If it is 0, then it is not in use and cannot be 
; modified.  An error message is printed telling the
; user to use the 'A' command to make a new entry and
; we jump back to GETCOM to await new instructions.

	; A = a valid entry number (1 to 63)
	lda	unit	  ; HL=addr of start of table
        cpi     0         ; does user want to modify part 0?
        cz      error     ; yes. says he can't!
        jz      GETCOM    ; and get next command
	call	ADDRfind  ; returned:
			  ; HL=addr of line in table
	mov	A,M	  ; A = 1st byte in the line
	cpi	0	  ; Is entry in use?
	jrnz	..prtHEAD ; Yes. We can proceed.
	lxi	H,badmodmsg
	call	prtmsg	  ; No.  Print `unused` msg
	JMP	GETCOM	  ; and await more commands.

;Print out the header for the line, and print it.
..prtHEAD:
        push    H         ; HL = addr of entry in table
	lxi	H,Headmsg
	call	prtmsg
	pop	H		; addr of selected line
	call	prtline		; print the Temp line
;Ask user if this listing is correct
..ASKifOK:
	lxi	H,VERIF2msg
	call	prtmsg
	call	CONIN	; get Y or N
	cpi	'N'
	jz	getCOM	; User wants to start over
	cpi	'Y'
	cnz	error	; incorrect entry 
	jrnz	..ASKifOK
; User has verified this as the line to modify.
; Proceed to request the new size, name, password,
; and control data.

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.
;User used the <CR> default option. Fill in old size.
	lda	unit	; Yes. Fill in old size.
Š	call	ADDRfind
;---------Test if the size stored in the table is a 0
	mov	A,M
	cpi	0	; Is the size in the table a 0?
	jrnz	..cont	; No.  We can assume its valid.
	call	error	; YES. Entry num is bad.
	jmpr	getSIZ	; and ask again.
;---------A zero entry means the end of the table.

; HL = address of unit in namebuf  table.
..cont:	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
	cpi	1	 ; size is less than 1?
	cc	error	 ; Tell user 'bad entry'
	jrc	getSIZ	 ; and ask again.
	sta	size	 ; save valid size value

;Test this size against the size stored in the table.
;Bypass this test if this is the latest line in table.
;If the size in the table is 0, any new size is 
;accepted.  Otherwise, if the sizes are different,
;warning messages are printed and we verify with the
;user that indeed a drastic change in file allocation
;will take place.
	lda	unit
	cpi	63	; Is this the last entry?
	jz	getNAM	; Yes. Bypass the test.
	call	ADDRfind; HL=addr of old size
	push	H	; Save if we dont bypass test
	lxi	D,16
	dad	D	; HL=next line in table
	mov	A,M	; A =next lines 'size'
	pop	H	; HL=addr of old size again
	cpi	0	; Is next line the end of tbl?
	jz	getNAM	; Yes. We can bypass test
;Test if user is modifying a size inside the table
	lda	size	; get new size in A
	cmp	M	; Are they the same?
	jrz	getNAM	; Yes. Proceed. Get the name
	mov	A,M	; No. Is this entry unused?
	cpi	0	; 0 means unused/open entry
	jrz	getNAM	; Yes. Proceed. Get the name
	; No. Print warning message
	lxi	H,WARNmsg
	call	prtmsg	; Light the lights, ring sirens
	lxi	H,Sizwarn
	call	prtmsg
	lxi	H,WARNend
	call	prtmsg	;
Š..getYN:lxi	H,WARNask
	call	prtmsg	; Ask user "want to go on?"
	call	CONIN	; Get y/n
	ani	0DFh	; make it upper case
	cpi	'N'
	jz	GETCOM	;  User doesnt want to go on
	cpi	'Y'
	cnz	error	; bad entry
	jrnz	..getYN	; ask again

;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?
	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?
	jrc	..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 
	jrnz	..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:	jmp	WBOOT	 ; Yes.

Scom:	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
	jmp	GETCOM
;--------------------------------------
; ZCOM- Zero out the table in memory  |
;       set partition zero to size 1  |
;--------------------------------------
 
Zcom:;BC=bytes to 0 out, HL=table addr
	lxi	B,16*64  ; length of table
	lxi	H,tablbuf; addr of table
        mvi     M,1      ; put a 0 into table
        inx     H        ; next table address
        dcx     B        ; decrement the counter
;     BC=bytes to 0 out, HL=table addr   
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
.page
Š;------------
;  Dcom  -   DELETE AN ENTRY IN THE TABLE. FIRST WE 
;            VERIFY THE ENTRY WITH THE USER, THEN
;	     DELETE THE ENTRY BY BUMPING DOWN ALL
;	     THE PROCEEDING TABLE ENTRIES. IF USER
;	     HAS CHOSEN AN ENTRY IN THE MIDDLE OF THE
;	     TABLE, A WARNING MESSAGE IS PRINTED.
; Get the entry number from the user. (0 to 63)
Dcom:	call	getUNT	 ; modify what unit number?
; Print out the line to be deleted.

	lxi	H,HEADmsg	;Print out the header
	call	prtmsg
	lda	unit
	call	ADDRfind	; Get table line addr
	call	prtline		; print the line
;Ask user if this listing is correct
..ASKifOK:
	lxi	H,VERIF3msg
	call	prtmsg
	call	CONIN	; get Y or N
	cpi	'N'
	jz	getCOM	; User wants to start over
	cpi	'Y'
	cnz	error	; incorrect entry 
	jrnz	..ASKifOK
;Check if user has picked an entry in the middle of
; table. If he has, print a warning message telling
; of the impending file destruction.
	lda	unit
	cpi	63	; last line of table?
	jrz	..Dlete	; Yes. We can delete this.
	inr	A	; No. Lets check next entry
	call	ADDRfind; HL=addr of next line in tbl
	mov	A,M	; A = 1st byte of next line
	cpi	0	; 0 means unused entry
	jrz	..Dlete	; We can delete line the user
			;wanted to without any damage.
	; Print warning message
	lxi	H,WARNmsg
	call	prtmsg	; Light the lights, ring sirens
	lxi	H,Delwarn
	call	prtmsg
	lxi	H,WARNend
	call	prtmsg	;
..getYN:lxi	H,WARNask
	call	prtmsg	; Ask user "want to go on?"
	call	CONIN	; Get y/n
	ani	0DFh	; make it upper case
	cpi	'N'
	jz	GETCOM	;  User doesnt want to go on
	cpi	'Y'
	cnz	error	; bad entry
	jrnz	..getYN	; ask again

; User wants to go ahead and delete.
; Delete a line in the table. Bump down higher entries.
Š..Dlete:lda	unit	; User wants to delete line
..kil1:	push	PSW
	call	movLINE	; bump down higher table line
	jrc	..done	; cry bit is set if were done
	pop	PSW
	inr	A	; increment unit number
	cpi	64
	jrnz	..kil1	; done if all 64 entries bumped
	push	PSW
..done:	pop	PSW	; just for stack balance
	lxi	H,COMPmsg
	call	prtmsg	; tell user function completed
	jmp	GETCOM	; and get the next command.

;---------
; Subroutine: movLINE
; Regs  in: 	A = line number in table
; Regs out:	none
; Destroyed:	any/all
;
; Bump down the next table entry into the given
;table entry line number.  
;We first test for the last entry number (63)
;and then we test for zeroed name entries. We 
;return with the carry bit set in either case.

movLINE:cpi	64
	stc		; set carry just in case
	rz		; we're at the top of the table

	push	PSW	; save our line num
	call	ADDRfind ; HL will be addr of line
	lxi	D,16
	xchg
	dad	D	 ; HL = addr of NEXT line num
			 ; DE = addr of given line num
	pop	PSW
	push	PSW	 ;Restore and resave line num
	cpi	63	 ;Is this the last line in tbl?
	jrz	..zerolin;Yes. Zero the line and ret 
;---Check for a 'zeroed out' following entry.
;   Zero out the given line if thats the case.	
	mov	A,M	 ; Check first byte for 0
	cpi	0	 ; Is this a deleted entry?
	jrnz	..cont	 ; NO. Continue with set up.
..zerolin:		 ; Zero line pointed to by DE
	mov	H,D	 ; Yes. Delete given line
	mov	L,E	 ; HL = addr of given line num
	inx	D	 ; DE = HL + 1
	mvi	M,0
	lxi	B,15	 ; Zero out 16 bytes total
	LDIR		 ; Zero out the given line.
	pop	PSW	 ; Rebalance the stack
	stc		 ; Set carry bit as flag.
	ret		 ; Rest of tbl is blank.
;---A 0 in the table would have meant no more entries.
..cont:	lxi	B,16	 ; 16 bytes per table line
	LDIR		 ; Bump down the next line into	
			 ; the given line number.

Š	pop	PSW	 ; restore line num
	ora	A	 ; Make sure cry bit is reset.
	ret		 ; One line has been bumped

.page
Š;**************************************************
;*                                                *
;*       CONSOLE I/O and PRINT SUBROUTINES        *
;*                                                *
;**************************************************

;-----
; 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


;---------
;		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: 	prtSPACE
;   Regs  in:	none
;   Regs out:	none
; Print how much space has been allocated
;as indicated by all the various 'sizes'
;stored in the DAT.
prtSPACE:
	call	ADDSIZ	 ; HL=sum of sizes (in K)
	call	cvtHLbcd ; C,D,E=sum of sizes (in BCD)
	mov	A,C
	sta	allospa	
	sded	allospa+1; save BCD of allocated space
	lxi	H,SPAmsg
	call	prtmsg	 ; tell user 'Allo Disk Space:'
	lda	allospa	 ; A=10Meg BCD part of allo spa
	ani	0Fh	 ; mask high bits
	ora	A	 ; No 10 Megabyte value?
	jrz	..prtM	 ; skip printing it then
	adi	'0'	 ; make it a printing char
	call	CONOUT	 ; and print it.
..prtM:	lded	allospa+1; Get 1Meg byte value
	push	D	 ; Save for 100K byte
	mov	A,D
	ora	A	 ; 1Meg value to print?
	jrz	..prtK	 ; No. Skip it.
	ani	0F0h	 ; mask low bits
	rrc
	rrc
	rrc
	rrc		 ; and put high bits in low
	adi	'0'	 ; and make it a prting char
	call	CONOUT	 ; Print 1Meg byte nibble
	mvi	A,','	
	call	CONOUT	 ; Print the comma, too.
..prtK:	pop	D	 ; Restore 100K char
	push	D	 ; and save it for 10K
	mov	A,D
	ani	0Fh	 ; mask high bits
	adi	'0'	 ; and make it printing
	call	CONOUT	 ; Print high BCD nibble,
	pop	D	 ; Restore 10K and 1K
	mov	A,E
	call	prtbyt	; print low BCD byte,
	lxi	H,endmsg
	call	prtmsg	; print 'M bytes',
	ret		; and were done.

.page
Š;******************************************
;*                                        *
;*       MISCELLANEOUS ROUTINES		  *
;*                                        *
;******************************************

;COUNT UP THE DISK SPACE THATS ALLOCATED
;The first byte of each line in the disk allocation
;table (DAT) is the size.  The DAT will be scanned
;and each size byte will be translated into a
;physical size.  A running sum of the physical
;sizes is kept, and it is saved when the end of
;the table (00) is found.


ADDSIZ:
	lxi	H,0
	shld	usedspa	;initialize space counter
	mvi	A,0
	call	ADDRfind;get starting DAT address

addup1:	push	H	;HL=start of a line in DAT
	mov	A,M	;A = size
	rlc
	rlc
	rlc		;A = size*8
	mvi	B,0
	mov	C,A	;BC= size*8 -- table offset
	lxi	H,..siztabl
	dad	B	;HL= addr in table
	PCHL		;jump into table

..siztabl:
;Size found is 0. Table is ended. Get ready to return.
       	pop	H	; rebalance the stack
	lhld	usedspa	; load HL with amt of used spa
	ret		; and return.
	nop
	nop
	noð		» Keeð ¸ byteó iî thió section

;Size found is 1
	lxi	B,256	; 1 means 256K
	jmp	addsum	; add this to sum
	nop
	noð		» Keeð ¸ byteó iî thió section

;Size found is 2
	lxi	B,512	; 2 means 512K
	jmp	addsum	; add this to sum
	nop
	noð		» Keeð ¸ byteó iî thió section

;Size found is 3
	lxi	B,1024	; 3 means 1 meg
	jmp	addsum	; add this to sum
Š	nop
	noð		» Keeð ¸ byteó iî thió section

;Size found is 4
	lxi	B,2048	; 4 means 2 meg
	jmp	addsum	; add this to sum
	nop
	noð		» Keeð ¸ byteó iî thió section

;Size found is 5
	lxi	B,4096	; 5 means 4meg
	jmp	addsum	; add this to sum
	nop
	noð		» Keeð ¸ byteó iî thió section

;Size found is 6
	lxi	B,8192	; 6 means 8meg

addsum:	lhld	usedspa	; get current total
	dad	B	; update it
	shld	usedspa	; and save it.
	pop	H	; Restore where we are in table
	lxi	D,16	; move to next line
	dad	D	; HL=next line addr
	jmp	addup1	; and keep on adding up lines

;----------
; Subroutine:	cvtHLbcd
; Regs  in:	HL = word to be converted to BCD
; Regs out:	C,D,E = three bytes in BCD format
;Destroyed:	A,HL
;Convert a register pair's contents to BCD
cvtHLbcd:
	lxi	D,00
	lxi	B,00
..tst:	mov	A,H	; HL is our hex counter
	ora	A
	jrnz	..addBCD
	ora	L	; Does HL=0
	rz		; we finished decrementing HL

..addBCD:
	dcx	H	; reduce hex count
	mov	A,E	; now increment decimal count
	adi	1
	daa
	mov	E,A	; put low BCD back byte in E
	jrnc	..tst	; decrement, test again.
	mov	A,D	; Since carry was set
	adi	1	; Increment next BCD byte.
	daa
	mov	D,A	; put high BCD back byte in D
	jrnc	..tst	; decrement, test again.
	mov	A,C	; Since carry was set
	adi	1	; Increment next BCD byte.
	daa
	mov	C,A	; put Meg BCD byte back in C
Š	jmpr	..tst	; decrement, test again.

;----------
;		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,DE
;Find an addr of a line in the table
;16 bytes per line
ADDRfind:
	lxi	H,TABLbuf ; start addr of table
	cpi	0	  ; first line of table?
	rz		  ; then were done
..1:	lxi	D,16	  ; incr table 16 bytes
	dad	D
	dcr	A	  ; decr table line number
	ora	A	  ; 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	1Bh	; 1B is ESC
	jz	GETCOM	; Auto jump to command level.
	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
        cpi     0	; is char just a null?
        jrnz    ..1	
        mvi	A,20h	; Yes. Print a space instead
..1:    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][tb]
	.ascii	'      ALLOC Command Summary '
	.ascii	[cr][lf][tb]
	.ascii	'--------------------------------'
	.ascii	[cr][lf][tb]'A - Add an '
	.ascii	'entry to the table'
	.ascii	[cr][lf][tb]'D - Delete an '
	.ascii	'entry in the table'
	.ascii	[cr][lf][tb]'E - Erase directory on disk'
	.ascii	[cr][lf][tb]'H - Print this Help summary'
Š	.ascii	[cr][lf][tb]'L - List out current table'
	.ascii	[cr][lf][tb]'M - Modify an '
	.ascii	'entry in the table'
	.ascii	[cr][lf][tb]'Q - Quit the program'
	.ascii	[cr][lf][tb]'S - Save as '
	.ascii	'the permanent table'
	.ascii	[cr][lf][tb]'Z - Zero out the entire table'
	.ascii	[cr][lf]
	.ascii	[cr][lf]'Use Control-C to abort '
	.ascii	'the program at any time.'
crlf:	.asciz	[cr][lf]
AIDmsg:	.asciz	'  Please type H for a command summary'
HEADmsg:.ascii	[cr][lf]'   Unit  Size     Name  '
	.ascii	'   Password  Ctrl'
	.ascii	[cr][lf]'   ----  ----     ----  '
	.asciz	'   --------  ----'
VERIFYmsg:
	.asciz [cr][lf]'Is this listing correct? '
VERIF2msg:
	.asciz [cr][lf]'Is this the entry to modify? '
VERIF3msg:
	.asciz [cr][lf]'Is this the entry to delete? '
NOGOmsg:.ascii	[cr][lf]'ALLOC cannot be used'
	.asciz	' on this station.'[cr][lf]
WARNmsg:.asciz	[cr][lf][bell][tb]' *** WARNING *** '
DELwarn:.asciz	[cr][lf]'DELETION OF THIS ENTRY'
SIZwarn:.asciz	[cr][lf]'CHANGING PARTITION SIZE'
WARNend:.ascii	[cr][lf]'WILL CAUSE ALL FOLLOWING'
	.ascii	[cr][lf]'ENTRIES TO HAVE THEIR '
	.asciz	[cr][lf]'FILES DESTROYED.'
WARNask:.asciz	[cr][lf][lf]'Do you wish to proceed? '

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  'Use ESC to restart, CTRL-C to abort. '
	.asciz	' Please try again.'
tblfulmsg:
	.ascii	[cr][lf]'Allocation table is filled.  '
	.asciz	'The modify command must be used.'
badmodmsg:
	.ascii	[cr][lf]'That line does not have an '
	.asciz	'entry.  Use the A (add) command.' 
addmsg:	.asciz	[cr][lf]'The next available line is '

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
NETbyt	=	11000000b ; byte assigns network 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
;
;----------
;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
	lda	sysflg
	cpi	0FFh	; use hard disk if MP/M
	jrz	..hddsk
	lda	47h	; get our user number
	cpi	0FFh	; Are we a hard disk?
	jrz	..hddsk	; Yes.
	mvi	M,NETbyt; No. Assign to network master
	ret
..hddsk:mvi	M,HDbyt	; assign unit 0 to a hard disk
	ret
;----------
;Subroutinx:  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
	lxi	B,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
	lxi	B,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

