;
;	****************
;	*	       *
;	*    cd.asm    *
;	*     v7.0     *
;	*	       *
;	****************
;
; 03/06/85 by Harry Kaemmerer CP/M-NET(tm) EAST (201) 249-0691
;	   this utility has ability to chain to a .com file.
;	   this program may be used by anyone for none profit.
;----------------------------------------------------------------------------
;Based on: FASTGO vers. 1.1, by James Whorton, 04/25/84 and GOTO vers. 7.0,
;by Harry Kaemmerer
;
;revisions in reverse order:
;
;03/06/85 made display independend of table entry size, deleted code
;	  that displayed the drive/user (not needed)	  - Harry Kaemmerer
;----------------------------------------------------------------------------
;when executed, this program does the following:
;
;1. checks for input, prints options and quits if none.
;2. evaluates input, seeking a match from the table.
;3. if no match found, tell user, display options and quit.
;4. on match, check for password status and get it if needed.
;5. if password doesn't match, abort.
;6. select specified user-area.
;
;  CD			displays usage and valid area_names
;  CD <area_name>	moves to area_name. if passworded,
;			gets same from user before moving.
;-----------------------------------------------------------------------
NO	EQU	0
YES	EQU	NOT NO
;-----------------------------------------------------------------------
;user settable options
;
USECLR	EQU	NO		;yes = clear screen works
CLR	EQU	26		;^Z = clear screen for kaypro
MAXWORD	EQU	4		;lenght of larest area_name entry in tabel
WIDTH	EQU	16		;# of columns to print across
;-----------------------------------------------------------------------
;equates section
;
SKIP	EQU	(13-MAXWORD)+12	;number of characters to skip when printing
				;DO NOT CHANGE......
BDOS	EQU	5		;bdos call vector
COUT	EQU	2		;console char. out
DIO	EQU	6		;direct i/o call
STUSR	EQU	32		;get/set user #
FCB	EQU	05CH		;first fcb
CR	EQU	13		;carraige return
LF	EQU	10		;line feed
BELL	EQU	7		;console bell
DEFBYT	EQU	4		;current drive/user byte
;
;-----------------------------------------------------------------------
;program starts here
;
	ORG	0100H
;
;the following code is the main body of the program.
;Check if user-area specified.
;
START:	LXI	H,0		;0 -> [HL]
	DAD	SP		;find caller's stack
	SHLD	SAVESP		;save for later
	LXI	SP,STACK	;set up our own stack
;
	 IF	USECLR
	MVI	A,CLR		;clr screen for kaypro
	CALL	CTYPE
	 ENDIF
;
	LDA	FCB+1		;get first byte of fcb
	CPI	32		;blank?
	JZ	USAGE		;yes, print usage and quit
;
;ok, a user-area was specified. Let's see how long it is
;
	MVI	B,0		;set up counter
	LXI	H,FCB+1		;set up pointer
;
LENCHK:	MOV	A,M		;get a byte
	INX	H		;increment pointer
	INR	B		;increment counter
	CPI	32		;is it a blank?
	JNZ	LENCHK		;no, go again
	MOV	A,B
	STA	USRLEN		;store count for later use
;
;now let's start checking the name specified against the table
;
	LXI	H,TABLE+2	;set up pointer
	SHLD	CHARP		;save pointer
;
NAMCHK:	LHLD	CHARP		;get table pointer
	MOV	A,M		;check for end of table
	CPI	0		;are we there?
	JZ	NOMAT		;yes, error message and usage
	LXI	D,FCB+1		;point to input
	LDA	USRLEN		;get length of input
	MOV	B,A		;move it to b
	CALL	COMPAR		;do the comparison
	JZ	MATCH		;it's a match, so do it
	LXI	D,25		;increment the pointer
	LHLD	CHARP		;get the pointer back
	DAD	D		;add it
	SHLD	CHARP		;save it
	JMP	NAMCHK		;try next entry
;
;a match was found, see if pwd protected
;
MATCH:	LHLD	CHARP		;get entry pointer
	DCX	H		;back up 1 bytes
	MOV	A,M		;get access code
	CPI	' '		;need a password?
	JZ	SELECT		;nope, go ahead and do it
				;get a password from user
	CALL	ILPRT		;prompt user
	DB	'Password: ',0
	LXI	H,USRPWD	;point to storage area
	MVI	B,0		;max chars allowed 10
;
PWD1:	PUSH	H
	PUSH	B
	MVI	E,0FFH		;see if char there
	MVI	C,DIO
	CALL	BDOS
	POP	B
	POP	H
	CPI	0		;char ready?
	JZ	PWD1		;not yet
	CPI	8		;back space?
	JZ	BSPACE		;do a backspace
	CPI	7FH		;rubout?
	JZ	BSPACE		;do a backspace
	CPI	CR		;end of input?
	JZ	PWD3		;yes
	MOV	M,A
	INX	H		;increment pointer
	INR	B		;increment char counter
	MOV	A,B		;get counter in a to check
	CPI	10		;buffer full?
	JZ	PWD3		;nope, get another char
	MOV	B,A
	JMP	PWD1
;
;do a backspace on input
;
BSPACE:	DCR	B		;move count to prior character
	DCX	H		;correct H also
	MVI	A,' '		;get a space
	MOV	M,A		;restore password storage
	JMP	PWD1		;and get a new character
;
;now do the check
;
PWD3:	LHLD	CHARP		;point to table entry
	LXI	D,13
	DAD	D
	LXI	D,USRPWD
	MVI	B,10		;check 10 chars (pwd length)
	CALL	COMPAR		;do a comparison
	JZ	SELECT		;correct password supplied
	CALL	ILPRT		;nope, say forget it
	DB	BELL,'Sorry, that area is not available.',CR,LF,0
	JMP	DONE		;display correct areas
;
;no option specified, or bad one, so list usage and table of definitions.
;
NOMAT:	CALL	ILPRT		;
	DB	CR,LF,BELL,'Entry not found.',CR,LF,0
;
USAGE:	CALL	ILPRT
	DB	CR,LF,'Usage: CD <Area_Name> moves you to your area.'
	DB	CR,LF,LF,0
;
;this routine prints the definition table. It prints <width> columns
;across and does not display any passwords.
;
	LXI	H,TABLE+2	;point to names
	MVI	D,MAXWORD	;# of bytes per entry to print
	MVI	B,WIDTH		;# of columns to print
;
;now send char and check for end of entry
;
INFO1:	MOV	A,M		;be sure it's there
	CPI	0		;end of tabel
	JZ	DONE		;yes...
	CALL	CTYPE		;send it
	INX	H		;increment pointer
	DCR	D		;decrement char counter
	MOV	A,D		;get char count to check
	CPI	0		;end of entry?
	JNZ	INFO1		;no, do another byte
;
;done with one entry, so evaluate first, skip past password section,
;print seperator and new line
;
	MVI	D,MAXWORD	;reset char counter
	MVI	A,SKIP		;# of chars to skip
;
SKIP0:	INX	H		;increment pointer
	DCR	A		;decrement char counter
	CPI	0		;past it yet?
	JNZ	SKIP0		;nope, not yet
;
	MOV	A,M		;get a character for end check
	CPI	0		;end of tabel
	JZ	DONE		;yes...
	DCR	B		;decrement column count
	MOV	A,B		;get count
	CPI	0		;need a new line?
	JZ	SKIP1		;yes
;
;add a seperator space between entries
;
	MVI	A,' '		;load a space for seperator
	CALL	CTYPE		;and send to the terminal
	JMP	INFO1		;now back to the grind
;
SKIP1:	MVI	A,CR		;start a new line
	CALL	CTYPE
	MVI	A,LF
	CALL	CTYPE
	MVI	B,WIDTH		;reset column counter
	MOV	A,M		;get a character for end check
	CPI	0		;end of tabel
	JZ	DONE		;yes...
	JMP	INFO1
;
DONE:	CALL	ILPRT
	DB	CR,LF,0
	LHLD	SAVESP		;get callers stack pointer -> [HL]
	SPHL			;now -> [SP]
	RET			;End of program!
;
;subroutines
;
;do a comparison, abort if match found compare routine, # of chars in b,
;text to check in de (input) and hl (table) if a match, zero flag will
;be set on exit
;
COMPAR:	LDAX	D		;get a char.
	CALL	UCASE		;make sure it's upper case
	CMP	M		;check it against text
	RNZ
	INX	H
	INX	D
	DCR	B
	JNZ	COMPAR
	RET
;
ILPRT:	XTHL
;
ILPLP:	MOV	A,M
	ORA	A
	JZ	ILPRET
	CALL	CTYPE
	INX	H
	JMP	ILPLP
;
ILPRET:	XTHL
	RET
;
CTYPE:	PUSH	B		;save registers
	PUSH	D
	PUSH	H
	MOV	E,A		;put character in e reg.
	MVI	C,COUT		;select conout
	CALL	BDOS		;do it
	POP	H		;restore registers
	POP	D
	POP	B
	RET			;done
;
UCASE:	CPI	061H		;converts lower case...
	RC			;in a to upper case
	CPI	07BH
	RNC
	ANI	05FH
	RET
;
;we got this far, let's change the user # and drive
;
SELECT:	LHLD	CHARP		;point to table
	DCX	H		;back up 2 bytes
	DCX	H
	MOV	A,M		;get value from table
	STA	DEFBYT		;put it in memory byte
	MOV	A,M		;get the byte
	ANI	0F0H		;mask out drive
	RAR			;rotate 4 times to get user #
	RAR			;in proper position
	RAR
	RAR
	MOV	E,A		;do it
	MVI	C,STUSR
	CALL	BDOS
	LDA	DEFBYT		;get user/drive byte
;
;----------------------------------------------------------------------------
; 04/20/84 by - Harry Kaemmerer
; auto chain to .com file routine for cp/m 2.2
; note "A" reg. must have user/drive info upon entry
;
	PUSH	PSW		;save drive/user
	CALL	ILPRT
;
	 IF	USECLR
	DB	CLR
	 ENDIF
;
	DB	CR,LF,'Standby... ',0
	POP	PSW		;get user/drive info
	MVI	D,0		;insure d register is zero
	MOV	E,A		;drive/user from a to e
	MVI	C,37		;reset drive/user
	CALL	BDOS		;do it
	LHLD	1		;get bios jump table address
	MOV	A,H		;move jump vector in a << lh reversed
	SUI	16H		;change to start of ccp location
	MOV	H,A		;return to h register
	MVI	L,0		;make cold start address
	SHLD	CCPLOC		;and save it for jump vector
	MVI	L,7		;move offset to l
	XCHG			;put in de
	LXI	H,FNAM		;location of file name
;
LLOOP:	MOV	A,M		;get character
	INX	H		;increment from pointer
	XCHG			;swap hl with de
	MOV	M,A		;place character in memory
	CPI	0		;look for a zero
	JZ	JUMP		;fake jump to cold boot vector
	INX	H		;increment to: pointer
	XCHG			;swap hl with de
	JMP	LLOOP		;not done
;
JUMP:	DB	0C3H		;we need a jump instruction and next 2 bytes
CCPLOC:	DB	0,0		;become the jump address
;
; finish
;----------------------------------------------------------------------------
;storage area
;
USRPWD:	DB	32,32,32,32,32	;force ten spaces for password...
	DB	32,32,32,32,32	;input and compare storage space...
CHARP:	DS	2		;next char. address pointer
USRLEN:	DS	1		;length of user-area specified
	DS	64
STACK:	DS	2		;new stack
SAVESP:	DS	2		;old stack
;
;--------------------------------------------------------------------
;change as needed the name of file or command to CHAIN to:
;
FNAM:	DB	3,'DIR',0	;number of bytes in name & file name to run
;		|   |	|
;		|   |	+--->	must be a zero
;		|   +------->	file or command name (must be in UPPER case)
;		+----------->	number of characters in name above.
;
;--------------------------------------------------------------------
;definition table.
;
;byte	   purpose
;--------- ----------------------------------------------------------
;  1	   allways a zero (0)			  [ 1 byte ]
;  2	   user#  in Hex			  [ 1 byte ]
;  3	   drive# in Hex			  [ 1 byte ]
;  4	   access code (* for passworded)	  [ 1 byte ]
;  5	   area name				  [13 bytes]
;  6	   password (if indicated in access code) [10 bytes]
;
;examples: 000H=0A,001H=0B,010H=1A,011H=1B, etc.
;the examples may be changed, added to or deleted
;as long as the proper format is kept. all entries
;in table should be in upper case.
;
;format guide.. 123H,'455555555555556666666666'
;
TABLE:
;
	DB	000H,' A0                     '
	DB	010H,' A1                     '
	DB	020H,' A2                     '
	DB	030H,' A3                     '
	DB	040H,' A4                     '
	DB	050H,' A5                     '
	DB	060H,' A6                     '
	DB	070H,' A7                     '
	DB	080H,' A8                     '
	DB	090H,' A9                     '
	DB	0A0H,' A10                    '
	DB	0B0H,' A11                    '
	DB	0C0H,' A12                    '
	DB	0D0H,' A13                    '
	DB	0E0H,' A14                    '
	DB	0F0H,' A15                    '
;
	DB	001H,'pB0           123456    '
	DB	011H,' B1                     '
	DB	021H,' B2                     '
	DB	031H,' B3                     '
	DB	041H,' B4                     '
	DB	051H,' B5                     '
	DB	061H,' B6                     '
	DB	071H,' B7                     '
	DB	081H,' B8                     '
	DB	091H,' B9                     '
	DB	0A1H,' B10                    '
	DB	0B1H,' B11                    '
	DB	0C1H,' B12                    '
	DB	0D1H,' B13                    '
	DB	0E1H,' B14                    '
	DB	0F1H,' B15                    '
;
	DB	002H,' C0                     '
	DB	012H,' C1                     '
	DB	022H,' C2                     '
	DB	032H,' C3                     '
	DB	042H,' C4                     '
	DB	052H,' C5                     '
	DB	062H,' C6                     '
	DB	072H,' C7                     '
	DB	082H,' C8                     '
	DB	092H,' C9                     '
	DB	0A2H,' C10                    '
	DB	0B2H,' C11                    '
	DB	0C2H,' C12                    '
	DB	0D2H,' C13                    '
	DB	0E2H,' C14                    '
	DB	0F2H,' C15                    '
;
	DB	003H,' D0                     '
	DB	013H,' D1                     '
	DB	023H,' D2                     '
	DB	033H,' D3                     '
	DB	043H,' D4                     '
	DB	053H,' D5                     '
	DB	063H,' D6                     '
	DB	073H,' D7                     '
	DB	083H,' D8                     '
	DB	093H,' D9                     '
	DB	0A3H,' D10                    '
	DB	0B3H,' D11                    '
	DB	0C3H,' D12                    '
	DB	0D3H,' D13                    '
	DB	0E3H,' D14                    '
	DB	0F3H,' D15                    '
;
	DB	004H,' E0                     '
	DB	014H,' E1                     '
	DB	024H,' E2                     '
	DB	034H,' E3                     '
	DB	044H,' E4                     '
	DB	054H,' E5                     '
	DB	064H,' E6                     '
	DB	074H,' E7                     '
	DB	084H,' E8                     '
	DB	094H,' E9                     '
	DB	0A4H,' E10                    '
	DB	0B4H,' E11                    '
	DB	0C4H,' E12                    '
	DB	0D4H,' E13                    '
	DB	0E4H,' E14                    '
	DB	0F4H,' E15                    '
;
	DB	005H,' F0                     '
	DB	015H,' F1                     '
	DB	025H,' F2                     '
	DB	035H,' F3                     '
	DB	045H,' F4                     '
	DB	055H,' F5                     '
	DB	065H,' F6                     '
	DB	075H,' F7                     '
	DB	085H,' F8                     '
	DB	095H,' F9                     '
	DB	0A5H,' F10                    '
	DB	0B5H,' F11                    '
	DB	0C5H,' F12                    '
	DB	0D5H,' F13                    '
	DB	0E5H,' F14                    '
	DB	0F5H,' F15                    '
;
	DB	006H,' G0                     '
	DB	016H,' G1                     '
	DB	026H,' G2                     '
	DB	036H,' G3                     '
	DB	046H,' G4                     '
	DB	056H,' G5                     '
	DB	066H,' G6                     '
	DB	076H,' G7                     '
	DB	086H,' G8                     '
	DB	096H,' G9                     '
	DB	0A6H,' G10                    '
	DB	0B6H,' G11                    '
	DB	0C6H,' G12                    '
	DB	0D6H,' G13                    '
	DB	0E6H,' G14                    '
	DB	0F6H,' G15                    '
;
	DB	007H,'pH0           12345678  '
	DB	017H,' H1                     '
	DB	027H,' H2                     '
	DB	037H,' H3                     '
	DB	047H,' H4                     '
	DB	057H,' H5                     '
	DB	067H,' H6                     '
	DB	077H,' H7                     '
	DB	087H,' H8                     '
	DB	097H,' H9                     '
	DB	0A7H,' H10                    '
	DB	0B7H,' H11                    '
	DB	0C7H,' H12                    '
	DB	0D7H,' H13                    '
	DB	0E7H,' H14                    '
	DB	0F7H,' H15                    '
;
	DB	008H,' I0                     '
	DB	018H,' I1                     '
	DB	028H,' I2                     '
	DB	038H,' I3                     '
	DB	048H,' I4                     '
	DB	058H,' I5                     '
	DB	068H,' I6                     '
	DB	078H,' I7                     '
	DB	088H,' I8                     '
	DB	098H,' I9                     '
	DB	0A8H,' I10                    '
	DB	0B8H,' I11                    '
	DB	0C8H,' I12                    '
	DB	0D8H,' I13                    '
	DB	0E8H,' I14                    '
	DB	0F8H,' I15                    '
;
	DB	009H,' J0                     '
	DB	019H,' J1                     '
	DB	029H,' J2                     '
	DB	039H,' J3                     '
	DB	049H,' J4                     '
	DB	059H,' J5                     '
	DB	069H,' J6                     '
	DB	079H,' J7                     '
	DB	089H,' J8                     '
	DB	099H,' J9                     '
	DB	0A9H,' J10                    '
	DB	0B9H,' J11                    '
	DB	0C9H,' J12                    '
	DB	0D9H,' J13                    '
	DB	0E9H,' J14                    '
	DB	0F9H,' J15                    '
;note: the following 4 bytes must be kept at the end of this table!
	DB	0,0,0,0		;<<<--- must be here....
;
	END
