*****************************************************************************
;
;  WRITECPM - This program runs under System-88 (Exec) and writes the CP/M
;	image file specified on the command line to the boot tracks of the
;	disk in drive 2. The first four sectors of the CP/M disk must look
;	like a valid System-88 (Exec) directory in order to work with the
;	Poly-8813 boot ROM, so this program computes and inserts the
;	directory checksum into the first sector based on the data in the
;	first four sectors of the file.
;
;	Rev	 Date	    Desc
;	1.0	11/02/19    M. Douglas, Original
;
;*****************************************************************************

; Poly PROM equates

USER	equ	3200h		;start of user programs
CONOUT	equ	0C24h		;console output wormhole 1
CMPTR	equ	2DC7h		;command line pointer

Dio	equ	0406h		;disk I/O
Msg	equ	040Ch		;display text string
Err	equ	040Fh		;display error from DE and enter Exec
Gover	equ	0415h		;load and execute overlay

; Misc equates

CR	equ	0Dh		;ASCII for carriage return

;-----------------------------------------------------------------------------
;  Start of code
;-----------------------------------------------------------------------------
	org	USER		;standard Exec program load address

	jmp	start		;first entry jump vector
	jmp	start		;re-entry jump vector (keep this)

start	lxi	h,0		;save stack pointer in savStk
	dad	sp
	shld	savStk

	call	fOpen		;open filename specified on command line
	call	read		;read the file into memory
	call	chkSum		;compute and store directory checksum
	call	write		;write boot tracks on drive 2
	lxi	h,mDone		;HL->'File written' message
	call	Msg
				;fall into program exit
				
pgmExit	lhld	savStk		;restore stack pointer
	sphl

	mvi	a,CR		;CR to console
	call	CONOUT
	
	ret			;exit to Exec
	
;-----------------------------------------------------------------------------
; fOpen - Open the input file specified on command line.
;    If no input file is provided, display program usage information and
;    exit. If the file does not exist, display the error and exit.
;    Otherwise, copy the disk start address and file size to to dskAddr
;    and numSecs.
;-----------------------------------------------------------------------------
fOpen	lhld	CMPTR		;HL->command line parameters
	mov	a,m		;anything entered?
	cpi	CR
	jz	errHelp		;no file specified, exit with help message

	lxi	d,fdeBuf	;DE->buffer for FDE returned by Gfid
	mvi	a,40h		;lookup the file name pointed to by HL
	call	Gover		;call Gfid overlay
	db	'Gfid'
	jc	err0705		;can't find file error

	lxi	h,fdeBuf+1	;HL->1st byte of the FDE
	mov	a,m		;A=byte with filename length
	ani	1Fh		;A=filename length alone
	adi	3		;A=filename+extension length+1

	mvi	d,0		;form DE=offset past filename extension
	mov	e,a
	dad	d		;HL->disk address past filename extension

	lxi	d,dskaddr	;DE->start of local copy of FDE fields
	mvi	b,4		;number of bytes to copy

foLoop	mov	a,m		;copy from FDE to local fields
	stax	d
	inx	h
	inx	d
	dcr	b
	jnz	foLoop
	
	ret
	
;-----------------------------------------------------------------------------
; read - Read the input file into memory
;-----------------------------------------------------------------------------
read	lda	fdeBuf		;1st byte contains drive number
	ani	0Fh		;get drive number alone
	mov	c,a		;C=drive to use
	
	lxi	d,fileBuf	;DE->file in memory	
	mvi	b,1		;B=read command
	lhld	dskAddr		;HL=disk address (sector) from the FDE
	lda	numSecs		;A=number of sectors to read
	call	DIO		;issue read command (in PROM)
	jc	Err		;disk I/O error

	ret

;-----------------------------------------------------------------------------
; write - Write the image file to the boot tracks in drive 2
;-----------------------------------------------------------------------------
write	mvi	c,2		;C=drive to use
	lxi	d,fileBuf	;DE->file in memory
	lxi	h,0		;HL=disk address (track 0, sector 0)	
	mvi	b,0		;B=write command
	lda	numSecs		;A=number of sectors to write
	call	DIO		;issue write command (in PROM)
	jc	Err		;disk I/O error
	
	ret			;exit if no error

;-----------------------------------------------------------------------------
; chkSum - The first four sectors must must look like a valid Exec
;    directory including the checksum of the first four sectors which
;    is stored in the first byte of sector 0.
;-----------------------------------------------------------------------------
chkSum	lxi	h,fileBuf+1	;HL->first byte to sum
	lxi 	b,4*256-1	;sum four sectors less one byte
	xra	a		;init sum to zero
	
csLoop	add	m		;add byte into checksum
	mov	d,a		;save sum in D
		
	inx	h		;point to next byte
	dcx	b		;decrement byte count
	mov	a,b		;reach zero?
	ora	c

	mov	a,d		;restore sum into A
	jnz	csLoop
	
	sta	fileBuf		;put checksum in 1st byte of sector 0
	ret

;-----------------------------------------------------------------------------
; Error processing
;-----------------------------------------------------------------------------
; errHelp - Display program info and usage, exit to Exec

errHelp	lxi	h,mHelp		;HL->help message 
 	call	Msg		;display it
 	jmp	pgmExit		;exit
 	
; err0705 - Display file not found error, exit to Exec

err0705	lxi	d,0705h		;error=file not found
	jmp	Err		;display error and exit to Exec

;-----------------------------------------------------------------------------
;   Data Area
;-----------------------------------------------------------------------------
mHelp	db	CR
	db	'WRITECPM Ver 1.0 for System-88 (Exec)',CR
	db	'  Writes a CP/M boot image file to the boot tracks',CR
	db	'  of the disk in drive 2.',CR
	db	CR
	db	'Usage: WRITEIMG file.ext',CR,0
	
mDone	db	'Boot tracks written on drive 2',CR,0

;**************************************************************************
; 
;  Data area
;
;**************************************************************************
fdeBuf	ds	44		;FDE as returned by Gfid
savStk	ds	2		;saved entry stack pointer

; Copy of data from the FDE. These fields MUST REMAIN IN THIS ORDER

dskAddr	ds	2		;starting disk address of file (FDA)
numSecs	ds	2		;number of sectors in file (DNS)

; File buffer runs from here to the end of memory

	org	($+0FFh) AND 0FF00h	;align to next page boundary
fileBuf	equ	$

	end

