;
;  Program:  STARTUP
;  Author:  Richard Conn
;  Version:  1.4
;  Date:  9 Jan 83
;  Previous Versions:  1.3 (7 Jan 83)
;  Previous Versions:  1.2 (6 Jan 83), 1.1 (7 Dec 82), 1.0 (8 Nov 82)
;
;	STARTUP loads the ZCPR2 command line with an initial command string
; for execution on cold boot.  The user may specify what this command string
; is to STARTUP in an interactive mode, and STARTUP may be configured at
; any time.
;
vers	equ	14

;
;	This program is Copyright (c) 1982, 1983 by Richard Conn
;	All Rights Reserved
;
;	ZCPR2 and its utilities, including this one, are released
; to the public domain.  Anyone who wishes to USE them may do so with
; no strings attached.  The author assumes no responsibility or
; liability for the use of ZCPR2 and its utilities.
;
;	The author, Richard Conn, has sole rights to this program.
; ZCPR2 and its utilities may not be sold without the express,
; written permission of the author.
;


;
;  Externals
;
	ext	print,bbline,initfcb
	ext	f$delete,f$make,f$write,f$close
	ext	cin,cout,caps,crlf
	ext	eval,padc,phl4hc
	ext	shftlh,pstr
	ext	fname,bdos
	ext	codend

;
;  Constants
;
fcb	equ	5ch
cr	equ	0dh
lf	equ	0ah

;
;  Branch to Start of Program
;
	jmp	start

;
;******************************************************************
;
;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
;
;	This data block precisely defines the data format for
; initial features of a ZCPR2 system which are required for proper
; initialization of the ZCPR2-Specific Routines in SYSLIB.
;

;
;  EXTERNAL PATH DATA
;
EPAVAIL:
	DB	0FFH	; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
EPADR:
	DW	40H	; ADDRESS OF EXTERNAL PATH IF AVAILABLE

;
;  INTERNAL PATH DATA
;
INTPATH:
	DB	0,0	; DISK, USER FOR FIRST PATH ELEMENT
			; DISK = 1 FOR A, '$' FOR CURRENT
			; USER = NUMBER, '$' FOR CURRENT
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0	; DISK, USER FOR 8TH PATH ELEMENT
	DB	0	; END OF PATH

;
;  MULTIPLE COMMAND LINE BUFFER DATA
;
MCAVAIL:
	DB	000H	; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
MCADR:
	DW	0FF00H	; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE

;
;  DISK/USER LIMITS
;
MDISK:
	DB	4	; MAXIMUM NUMBER OF DISKS
MUSER:
	DB	31	; MAXIMUM USER NUMBER

;
;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
;
DOK:
	DB	0FFH	; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
UOK:
	DB	0FFH	; ALLOW USER CHANGE? (0=NO, 0FFH=YES)

;
;  PRIVILEGED USER DATA
;
PUSER:
	DB	10	; BEGINNING OF PRIVILEGED USER AREAS
PPASS:
	DB	'chdir',0	; PASSWORD FOR MOVING INTO PRIV USER AREAS
	DS	41-($-PPASS)	; 40 CHARS MAX IN BUFFER + 1 for ending NULL

;
;  CURRENT USER/DISK INDICATOR
;
CINDIC:
	DB	'$'	; USUAL VALUE (FOR PATH EXPRESSIONS)

;
;  DMA ADDRESS FOR DISK TRANSFERS
;
DMADR:
	DW	80H	; TBUFF AREA

;
;  NAMED DIRECTORY INFORMATION
;
NDRADR:
	DW	00000H	; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
NDNAMES:
	DB	64	; MAX NUMBER OF DIRECTORY NAMES
DNFILE:
	DB	'NAMES   '	; NAME OF DISK NAME FILE
	DB	'DIR'		; TYPE OF DISK NAME FILE

;
;  REQUIREMENTS FLAGS
;
EPREQD:
	DB	000H	; EXTERNAL PATH?
MCREQD:
	DB	0FFH	; MULTIPLE COMMAND LINE?
MXREQD:
	DB	000H	; MAX USER/DISK?
UDREQD:
	DB	000H	; ALLOW USER/DISK CHANGE?
PUREQD:
	DB	000H	; PRIVILEGED USER?
CDREQD:
	DB	000H	; CURRENT INDIC AND DMA?
NDREQD:
	DB	000H	; NAMED DIRECTORIES?
Z2CLASS:
	DB	0	; CLASS 0
	DB	'ZCPR2'
	DS	10	; RESERVED

;
;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
;
;******************************************************************
;

;
;  Start of Program
;
start:
	lda	mcavail	;multiple commands available?
	ora	a	;0=no
	jz	mcerr
	call	codend	;allocate buffer space
	shld	oldcmd	;256 bytes for old command line
	lda	fcb+1	;check for option char
	cpi	' '	;no option if <sp>
	jz	run	;run command
	cpi	'S'	;setup?
	jz	setup
	call	banner	;print banner
	call	print	;print help message
	db	cr,lf,'STARTUP is used to execute an initial set of commands'
	db	cr,lf,'  under ZCPR2 with Multiple Commands implemented.'
	db	cr,lf
	db	cr,lf,'STARTUP is invoked by one of the following command'
	db	cr,lf,'  lines:'
	db	cr,lf
	db	cr,lf,'	STARTUP		<-- execute built-in commands'
	db	cr,lf,'	STARTUP SETUP	<-- define built-in commands'
	db	cr,lf,'			    (only the S in SETUP is needed)'
	db	cr,lf,0
	ret
;
;  Multiple Command Line Buffer not Supported -- Fatal Error
;
mcerr:
	call	banner
	call	print
	db	cr,lf,'Multiple Command Line is not supported.'
	db	cr,lf,'STARTUP is based on the use of this buffer,'
	db	cr,lf,'and STARTUP cannot function without it.'
	db	cr,lf,'STARTUP is aborting.'
	db	cr,lf,0
	ret
;
;  Print Startup Banner
;
banner:
	call	print
	db	'STARTUP, Version '
	db	vers/10+'0','.',(vers mod 10)+'0'
	db	0
	ret

;
;  Run STARTUP Command Line
;
run:
	lhld	oldcmd	;pt to save buffer
	xchg		;... in DE
	lhld	mcadr	;get base of command line
	mov	a,m	;low-order address in A
	inx	h
	mov	h,m	;high-order address in H
	mov	l,a	;low-order address in L
run0:
	mov	a,m	;get char
	stax	d	;put it
	inx	h	;pt to next
	inx	d
	ora	a	;end of line?
	jnz	run0
	lhld	mcadr	;pt to base address of command line
	push	h	;save ptr
	lxi	d,4	;pt to command line byte
	dad	d	;hl pts to command line byte
	xchg		;... de pts to it
	pop	h	;get ptr to base
	mov	m,e	;store address
	inx	h
	mov	m,d
	xchg		;hl pts to first byte of command line
	shld	byte1	;save ptr in case of error
	lxi	d,cmnd	;pt to STARTUP Buffer
	push	h	;save HL for now
	lhld	mcadr	;address of multiple command line buffer
	inx	h	;skip ptr
	inx	h	;pt to buffer size
	mov	b,m	;... in B
	pop	h	;restore HL
	call	stline	;store line
	jz	err	;line too long?
	dcx	h	;pt to ending null
	xchg
	lhld	oldcmd	;pt to old command line
	xchg		;... in DE
	call	stline
	jz	err	;line too long?
	ret
err:
	call	banner
	call	print
	db	cr,lf,7,'** Command Line too Long -- Abort **',0
	lhld	byte1	;clear line
	mvi	m,0
	ret
;
;  Store commands pted to by DE in buffer pted to by HL; B=space left in buffer
;
stline:
	ldax	d	;get byte of command
	mov	m,a	;store it
	inx	h	;pt to next
	inx	d
	dcr	b	;count down
	jz	stlerr
	ora	a	;done?
	jnz	stline
	mvi	a,0ffh	;set no error
	ora	a
	ret
stlerr:
	xra	a	;error
	ret
;
;  STARTUP Setup Mode
;
setup:
	call	banner
cloop:
	call	print
	db	cr,lf,'STARTUP Setup Command (?=Help)? ',0
	call	capin	;get response, capitalize, and echo
	cpi	'C'	;define command line
	jz	setupc
	cpi	'D'	;display values
	jz	setupd
	cpi	'X'	;exit
	jz	setupx
	call	print	;print help message
	db	cr,lf,'  Setup Mode Commands are --'
	db	cr,lf,'	C -- Define STARTUP Multiple Command Line'
	db	cr,lf,'	D -- Display STARTUP Values'
	db	cr,lf,'	X -- Exit and Optionally Rewrite STARTUP'
	db	0
	jmp	cloop
;
;  Set STARTUP Multiple Command Line Buffer Contents
;
setupc:
	call	print
	db	cr,lf,'	Current Multiple Command Buffer Contents is --',cr,lf,0
	lxi	h,cmnd	;pt to line
	call	pstr
	call	print
	db	cr,lf,'	New Line? ',0
	xra	a	;no caps
	call	bbline	;get line from user
	lxi	d,cmnd	;pt to command line
copy:
	mov	a,m	;get byte
	stax	d	;put byte
	inx	h	;pt to next
	inx	d
	ora	a	;done?
	jnz	copy	;fall thru to setupd to display result
;
;  Display Values
;
setupd:
	call	print
	db	cr,lf
	db	cr,lf,'	Multiple Command Line --',cr,lf,'	--->',0
	lxi	h,cmnd	;pt to buffer
	call	pstr	;print it
	call	crlf	;new line
	jmp	cloop	;get next command

;
;  Exit to OS with optional rewrite of STARTUP.COM
;
setupx:
	call	print
	db	cr,lf,'	Do you wish to update STARTUP (Y/N/<CR>=Y)? ',0
	call	capin	;get response, capitalize, and echo
	cpi	'N'	;no?
	rz		;done if so
	call	print
	db	cr,lf,'	STARTUP will write file to current disk/user',0
file:
	call	print
	db	cr,lf,'	STARTUP File is ',0
	lxi	h,sfcb+1	;pt to FN field
	call	prfn	;print file name
	call	print
	db	cr,lf,'	Enter New File Name or <CR> if OK: ',0
	mvi	a,0ffh	;capitalize
	call	bbline	;get line
	ora	a	;any input?
	jz	write
	lxi	d,sfcb	;pt to FCB
	call	fname	;convert into FCB
	mov	a,b	;anything other than default given?
	ana	c
	cpi	0ffh	;must be FF if both defaults
	jz	file
	call	print
	db	cr,lf,'	** Disk or User Specification Ignored **',0
	jmp	file
prfn:
	mvi	b,8	;8 chars
	call	prch
	mvi	a,'.'
	call	cout
	mvi	b,3	;3 chars
prch:
	mov	a,m	;get char
	call	cout	;output it
	inx	h	;pt to next
	dcr	b	;count down
	jnz	prch
	ret
capin:
	call	cin	;get response
	call	caps
	jmp	cout
;
;  Begin procedure to write file to disk
;
write:
	call	print
	db	cr,lf,'	Writing File ',0
	lxi	h,sfcb+1	;print file name
	call	prfn
	call	print
	db	' to Disk ... ',0
	lxi	d,sfcb	;pt to fcb
	call	initfcb	;init it
	call	f$delete	;delete it
	call	initfcb	;reinit it
	call	f$make	;create file
	cpi	0ffh	;error?
	jz	derr
	call	codend	;get end of code
	call	shftlh	;shift HL left 1 bit so we have a block (128 byte)
			;count
	mov	b,h	;count in b
	lxi	h,100h	;pt to start of program
writel:
	xchg		;de is dma address
	push	h	;save HL
	mvi	c,26	;set dma address
	call	bdos
	lxi	h,80h	;pt to next block
	dad	d
	pop	d	;get de (ptr to sfcb), hl pts to next block
	call	f$write	;write block to disk
	ora	a	;0=ok
	jnz	derr
	dcr	b	;count down
	jnz	writel
	call	f$close	;close file
	call	print
	db	'Done',0
	ret
derr:
	call	print
	db	cr,lf,'	Disk Output Error -- Aborting',0
	ret

;
;  Buffers
;
oldcmd:
	ds	2	;original command line
byte1:
	ds	2	;ptr to first byte
cmnd:
	db	0	;empty line initially
	ds	256	;buffer for command line

;  FCB to write STARTUP to
sfcb:
	db	0	;current disk
	db	'STARTUP COM'
	ds	4
	ds	16
	ds	4

	end
