;====================================================
; STARTER A.K.A. START MAKER by Claude Ostyn        :
; Version 3  9/27/83				    :	
;						    :
; This is a self-modifying program with hooks into  :	
; CCP and BDOS.  Use extreme caution.		    :	
;==================================================== 	
;EQUATES

; ASCII
cr	equ	0dh
lf	equ	0ah
ctrlz	equ	1ah
escape  equ	27
half	equ	')'
full	equ	'('
; BDOS functions
rconf	equ	1			;read CON: into A
wconf	equ	2			;write A to CON:
rbuff	equ	10			;read a console line
; CP/M disk access functions
initf	equ	13			;initialize BDOS
openf	equ	15			;open file
closf	equ	16			;close file
findf	equ	17			;find file
delef	equ	19			;delete file
readf	equ	20			;read one record
writf	equ	21			;write one record
makef	equ	22			;create file
sdmaf	equ	26			;set DMA function
; CP/M addresses
rboot	equ	0			;cold boot
drive	equ	4			;current drive
bdos	equ	5			;BDOS entry for calls
memax	equ	7			;MSB of top memory
tfcb	equ	5ch			;transient file control block
fcbex	equ	tfcb+12			;file extent
fcbs2	equ	tfcb+14			;system use in FCB
fcbrc	equ	tfcb+15			;record count in FCB
fcbcr	equ	tfcb+32			;current record in FCB
tbuff	equ	80h			;transient buffer
tpa	equ	100h			;TPA
; CP/M flags
bdaok	equ	0			;BDOS return for all OK
bder1	equ	1			;BDOS return 1
bder2	equ	2			;BDOS return 2
bderr	equ	255			;BDOS return error flag
; special values for this program
imagelen	equ	4		;number of records in AUTOST

;START
   		org	tpa
tempjmp:	jmp	maker		;this jump will be changed to nop
					;by program		

;AUTOSTART PROGRAM PART
	lhld	01
	mvi	l,0
	mov	a,h
	sui	16h
	mov	h,a
	shld	ccp
	lxi	d,message2
	call	print
	lxi	d,command
	lxi	b,42
 automove:
	lhld	ccp
	mvi	l,07
	call	again
	lhld	ccp
	mvi	l,88h
	mvi	a,08h
	mov	m,a
	lhld	ccp
	mvi	l,89h
	mov	a,h
	mov	m,a
	lhld	ccp
	pchl
again:
	ldax	d
	mov	m,a
	inx	h
	inx	d
	dcx	b
	mov	a,b
	ora	c
	jnz	again
	ret		
print:
	mvi	c,9
	jmp	bdos

;AUTOSTART STORAGE AREA
ccp:		ds	2
command: 	ds	84
message: 	ds	2
message2:	ds	88

;END OF AUTOST PROGRAM

maker:
start:		lxi	sp,stak		;set up user's stack
		lda	drive		;save initial drive selected
		sta	drsav
		xra	a
		sta	tempjmp		;cancel the jump to here
		sta	tempjmp+1
		sta	tempjmp+2
start1:		call    showmsg
		db	26,9,9,'STARTER',escape, half,'  Version 1.3',cr,lf,lf
		db	9,9,'Copyright 1983 Claude Ostyn',cr,lf,lf,lf
		db	escape,full,0
		mvi	a,imagelen	;length of AUTOST image
		lxi	h,recct		;in number of 128 byte records 
		mov	m,a		;store it at recct
		call	showmsg
sinon:		db	'This program will create another program called',cr,lf
		db	'AUTOST.COM and put it on a diskette in drive B.',cr,lf,lf
		db	'Ozzie looks for AUTOST.COM when it is booted.',cr,lf
		db	'If it finds it, it then executes the command',cr,lf
		db	'requested by AUTOST.COM.',cr,lf,lf,lf,lf
contline:	db	'Press <RETURN> to proceed, or CONTROL-Z to exit. ',0     
	
		call 	chrin		;get answer
		cpi	ctrlz		;control-z?
		jz	exit		;if yes, exit
start2:		call	blank		;blank input areas
		call	showmsg
promptfile:	db	26,cr,lf,lf
		db	'Enter the command to be executed by AUTOST.COM,'
		db	cr,lf,'(up to 80 characters).',cr,lf 
		db	'Example:   MBASIC ZAPGAME',cr,lf,lf,lf
		db	'________________________________________',cr,0
		lxi	h,inbuff		;set maximum input length 	
		mvi	m,80		;at 80
		lxi	d,inbuff
		mvi	c,rbuff
		call	bdos
		lxi	h,inbuff+1	;point to char. counter
		mov	a,m		
		cpi	0		;if zero, then
		jz	exit		;exit
		call	movcommand	;move command line into AUTOST
		call	showmsg
promptmessage:	db	cr,lf,lf,'Enter the message to be displayed while',cr,lf
		db	'AUTOST.COM is executing (up to 80 characters).',cr,lf,lf,lf
		db      '__________________________'
		db	'_________________________',cr,0
		lxi	d,message	;point to message area
		mvi	c,rbuff
		call	bdos		;and enter the message
		call	setend		;put cr/lf at end

copyit:		call	putname		;put B:AUTOST.COM into FCB
		call	showmsg
		db	cr,lf,lf
		db	'Put the disk on which you want to create',cr,lf
		db	'AUTOST.COM in drive B, and press any key,',cr,lf
		db	'or CTRL-Z to make changes.',cr,lf
		db	cr,lf,0
		call	chrin
		cpi	ctrlz
		jz	start2		
		call	showmsg
		db	lf,lf,9,9,'<<< WAIT >>>',0
		call	put
		call	showmsg
		db	'Copy this AUTOST.COM on another disk? ',0
		call	chrin
		cpi	'Y'
		jz	copyit
exit:		call	showmsg
		db	26,cr,lf,lf,9,'Returning to CP/M...',cr,lf,lf,0
		lda	drsav		;restore initial drive
		sta	drive
		jmp	rboot

;make changes at end of message
setend:
		lxi	h,message+1	;point to 1 before 1st chr
     	lookforend:
		inx	h
		mov	a,m
		cpi	'$'		;look for terminator
		jnz	lookforend
		mvi	m,cr		;and replace with cr/lf sequence
		inx	h
		mvi	m,lf
		inx	h
		mvi	m,lf
		inx	h
		mvi	m,'$'
		ret


; Write a file from "buffer" to disk

put:		lxi	h,tpa		;set up buffer start
		shld	next
		lda	recct		;save record count
		sta	ctsav
put1:		mvi	c,initf		;enable write on any disk
		call	bdos
		xra	a		;initialize FCB
		sta	fcbcr		;current record
		lxi	h,0
		shld	fcbex		;extent and s1
		shld	fcbs2		;s2 and record count
		lxi	d,tfcb		;see if file exists
		mvi	c,findf		;find function
		call	bdos
		cpi	bderr		;is it there?
		jz	put2
		call	showmsg
		db	cr,lf,'OK to erase existing AUTOST.COM? ' ,0
		call	chrin
		cpi	'Y'
		jnz	putex		;if no, try again
		call	showmsg
		db	escape,'R',0bh,0
		lxi	d,tfcb		;if yes, erase it
		mvi	c,delef
		call	bdos
put2:		lxi	d,tfcb
		mvi	c,makef
		call	bdos
		cpi	bderr
		jnz	put3
		call	wropn
		jmp	putex

put3:		lhld	next
		xchg
		mvi	c,sdmaf
		call	bdos
		lhld	next
		lxi	d,128
		dad	d
		shld	next
		lxi	d,tfcb
		mvi	c,writf
		call	bdos
		cpi	bdaok
		jz	put4
		call	wemsg
		jmp	putex
put4:		lda	recct
		dcr	a
		sta	recct
		jnz	put3
		call	cpdma
		lxi	d,tfcb
		mvi	c,closf
		call 	bdos
		lda	ctsav
		sta	recct
		call	showmsg
		db	cr,9,9,'<<< DONE! >>>',9,9,cr,lf,lf,9,0
putex:		call	showmsg
		db	cr,lf,0
		call	cpdma
		ret

; display write error message
wemsg:		call	showmsg
		db	cr,lf,lf,'Permanent write error',cr,lf,0
		ret

; display write open message
wropn:		call	showmsg
		db	cr,lf,lf,'Cannot open for write ',cr,lf,0
		ret

;restore CP/M DMA address to the transient buffer
cpdma:		lxi	d,tbuff
		mvi	c,sdmaf
		call	bdos	
		ret

;console character into register a, masked to 7 bits
chrin:		push	b
		push	d
		push	h
	readit:
		mvi	e,0ffh
		mvi	c,6
		call	bdos
		cpi	0
		jz	readit
		ani	7fh
		call	ucase
		call	cout
		pop	h
		pop	d
		pop	b
		ret

;character in register A output to console
cout:		push	b
		push	d
		push	h
		push	psw
		mvi	c,wconf
		mov	e,a
		call	bdos
		pop	psw
		pop	h
		pop	d
		pop	b
		ret

;message pointed to by stack out to console
showmsg:		xthl
		xra	a
		add	m
		inx	h
		xthl
		rz
		call	cout
		jmp	showmsg

;put name of new file into FCB
putname:
		mvi	a,2
		sta	tfcb		;force drive b designator
		lxi	d,filename
		lxi	h,tfcb+1	;point to name area
		mvi	b,11
        movname:
		ldax	d
		mov	m,a
		inx	h	
		inx	d
		dcr	b
		jnz	movname
		ret

; move the command line into AUTOST image
movcommand:
		lxi	h,command	;length of command in image
		lxi	d,inbuff+1	;point to character counter	
		ldax	d		;get it into a
		mov	m,a		;and put it in command
   		mov	b,a		;also copy it into b
		inx	d		;point to command itself
		inx	h		;do same in image
		mov	a,b		;put counter into a
		cpi	0		;check if zero
		rz			;if zero, return
   	moveit:
		ldax	d		;get byte to move
		call	ucase		;convert to upper-case if necessary
		mov	m,a		;move it
		inx	h		;increment destination
		inx	d		;increment source loc.
		dcr	b		;decrement counter
		jnz	moveit		;repeat
		ret

;convert to uppercase if letter
ucase:		
		cpi	':'		;first check that it is not
		rz			;one of the ASCII codes
		cpi	'{'		;larger than lower case
		rz			;and, if it is, just return
		cpi	'}'
		rz	
		cpi	'~'
		rz	
		cpi	'Z'+7		;lowercase?
		rc			;if not, don't convert
		ani	5fh		;convert to uppercase
		ret

;initialize input areas
blank:
		lxi	h,command	;command area
		mvi	b,82		;put zero in 82 bytes
	movzero:
		mvi	m,0
		inx	h
		dcr	b
		jnz	movzero
		lxi	h,message
		mvi	m,80
		inx	h
		mvi	m,0		;zero counter
		mvi	b,82
	movterm:			;put terminator in 82 bytes 
		inx	h
		mvi	m,'$'
		dcr	b
		jnz	movterm
		ret		

;RAM variables and buffers
drsav:		ds	1
recct:		ds	1
ctsav:		ds	1
next:		ds	2
;set up stack space
		ds	80
stak		db	0

;for filename, format is XXXXXXXXTYP to fit FCB image
filename:	db	'AUTOST  COM'
inbuff:	
		end 
