;
;	program XUSER.ASM
;
;       John Evancie   7/3/85
;
;	to extend the accessibility of CPM's user areas
;
;	User types: XUSER xx
;	and program switches into the selected user
;       area, or into user area 0 if no argument is
;       supplied. Before BDOS is called, the program
;       checks that the argument is less than 32.
;
;	After the area is selected, the program uses
;	BDOS to get it back, and display it at the
;	console. In this way, both uses of BDOS function
;	call #32 are illustrated (even if it is a BIT 
;       redundant)
;
;	It should be noted that this approach allows you
;	access to user areas 0 - 31, whereas access via
;	CCP is limited to user areas 0 - 15.
;
cr	equ	0dh		;carriage return
lf	equ	0ah		;line feed
uflag	equ	0ffh		;"get user" bdos value
pbuff	equ	09h		;"print string" bdos code
getus	equ	020h		;"get/set user" bdos code
fcb     equ     05ch
bdos	equ	05h
tpa     equ     0100h
;
	org 	tpa
;
	lxi	D,mess0		;startup message
	call	print
;
	lda	fcb+1		;check the command line
	cpi	020h		;is it blank?
	jnz	begin		;if not, take it apart below
;
	mvi	E,0		;if so, assume user wants user area 0
	jmp	ok		;and do it!
;
begin:	lda	fcb+2		;is the second character of the
	cpi	020h		;command line blank?
	jz	single		;if so, process the first one
;
	sui	030h		;if not, convert the ASCII char to hex
	mov	D,A		;and stash the result in DE
;
	lda	fcb+1		;look at the first character now
	cpi	020h		;is it blank?
	jnz	cnvt1		;if not, do further checking
	jmp	doit		;if so, assume user made a typo and proceed
;
cnvt1:	sui	030h		;convert to hex
	mov	B,A		;stash in B
	add	B
	add	B
	add	B
	add	B
	add	B		;lazy mans multiply by 10
	add	B
	add	B
	add	B
	add	B
	add	D		;and add back in the ones digit
	mov	E,A		;and store result in E
	jmp	doit		;you are now set up to make the switch
;
single:	lda	fcb+1		;grab the first and only digit
	sui	030h		;convert to hex
	mov	E,A		;move it into position for BDOS call
;
doit:	mov	A,E		;get choice back in A
	cpi	020h		;is it less that 32?
	jc	ok		;if so, do it finally
	jmp	endit		;if not, abort
;
ok:	mvi	C,getus		;put switch user code in C
	mvi	D,uflag		;set D to switch code (instead of E)
	call	bdos		;and do it
;
	mvi	a,0h
	lxi	d,mess2
	call    print
	mvi	c,getus		;now get ready to read back the user area
	mvi	d,0		;
	mvi	e,uflag		;E needs the switch code in order to read it back
	call 	bdos
;
	call	finis
	ret

finis:	call	cnvrt
	mvi	c,2
	mov	e,h
	push	b
	push	h
	call	bdos
	pop	h
	pop	b
	mov	e,l
	call	bdos
	ret
cnvrt:	push	psw
	ani	00001111b
	call	dovrt
	mov	l,a
	pop	psw
	rrc
	rrc
	rrc
	rrc
	ani	00001111b
	call	dovrt
	mov	h,a
	ret
dovrt:	cpi	0ah
	jc	num1
	adi	037h
	ret
num1:	adi	030h
	ret
endit:	lxi	D,mess1		;point to error message
	call	print		;print it
	ret
print:	mvi	c,pbuff
	call	bdos
	ret
;
mess0:	db	'XUSER.COM   V 1.0  7/3/85',cr,lf,'$'
mess1:	db	'Invalid area...',cr,lf
	db	'(valid areas are 0 - 31 inclusive)',cr,lf,lf,'$'
mess2:	db	'User Area selected: $'
;
end
