	TITLE	CP/M SYSTEM GENERATOR UTILITY  28 FEB 81  11:20
;*************************************************************
;
;   CP/M SYSGEN UTILITY FOR JADE FORMAT DISKS
;   (c) 1981  GRH Electronics, Cupertino, CA
;   By  Girvin Herr
;
;*************************************************************
;
;   This utility generates CP/M system on track 1 in Double
; Density.
;
;*************************************************************
	FORM
;*************************************************************
;
;  CP/M SYSTEM CONSTANTS
;
;************************
;
BDOS:	EQU	0005H
TPA:	EQU	0100H
;
CI:	EQU	1
CO:	EQU	2
OPEN:	EQU	15D
READ:	EQU	20D
;
DEFFCB:	EQU	005CH	;DEFAULT FCB ADDR
FCBCR:	EQU	DEFFCB+32D
;
DKSELO:	EQU	18H
TRKSLO:	EQU	1BH
SECSLO:	EQU	1EH
ADRSLO:	EQU	21H
RDSECO:	EQU	24H
WRSECO:	EQU	27H
;
SYBUFR:	EQU	0900H
;
ZERO:	EQU	0
;
BIOSNT:	EQU	0001H	;LOCATION OF BIOS START ADDRESS
;**********************
;
;  ASCII CONSTANTS
;
;*********************

LF:	EQU	0AH
CR:	EQU	0DH
ASPACE:	EQU	20H
;
	FORM
;*************************************************************
;
	ORG	TPA
;
	JP	START
;
	DB	'Copyright (c) 1981, GRH Electronics'
;
LASTRK:	DB	1
LSTSEC:	DB	48D
;
;  SECTOR TABLE
;
SECTBL:	EQU	$
SECX:	DB	1,2,3,4,5,6,7,8D,9D,10D,11D,12D,13D,14D,15D,16D
	DB	17D,18D,19D,20D,21D,22D,23D,24D,25D,26D,27D,28D
	DB	29D,30D,31D,32D,33D,34D,35D,36D,37D,38D,39D,40D
	DB	41D,42D,43D,44D,45D,46D,47D,48D
;
	DS	0175H-$
;
;   AX128 MULTIPLIES VALUE IN A BY 128D & FORMS WORD VALUE
;
AX128:	LD	L,A
	LD	H,ZERO
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	RET
;
;  CONSOLE INPUT
;
CONIN:	LD	C,CI	;GET CHAR
	CALL	BDOS
	CP	'a'	;IF LC THEN MAKE UC
	RET	C
	CP	'{'
	RET	NC
	AND	5FH
	RET
;
;   CONSOLE OUT
;
CONOUT:	LD	E,A
	LD	C,CO
	JP	BDOS
;
;  CR - LF
;
CRLF:	LD	A,CR
	CALL	CONOUT
	LD	A,LF
	JR	CONOUT
;
;  ED1 DOES CR-LF BEFORE EDITOR
;
ED1:	PUSH	HL
	CALL	CRLF
	POP	HL
;
;  EDITOR OUTPUTS STRING
;
EDITOR:	LD	A,(HL)	;GET CHAR
	OR	A	;IF CHAR = 0 THEN EXIT
	RET	Z
	PUSH	HL
	CALL	CONOUT
	POP	HL
	INC	HL
	JR	EDITOR
;
;  SELECT DISK
;
DKSEL:	LD	C,A
	LD	HL,(BIOSNT)	;GET BASE ADDR
	LD	DE,DKSELO	;ADD OFFSET
	ADD	HL,DE
	JP	(HL)
;
;   SET TRACK
;
TRKSL:	LD	HL,(BIOSNT)
	LD	DE,TRKSLO
	ADD	HL,DE
	JP	(HL)
;
;  SET SECTOR
;
SECSL:	LD	HL,(BIOSNT)
	LD	DE,SECSLO
	ADD	HL,DE
	JP	(HL)
;
;  SET ADDR
;
ADRSL:	LD	HL,(BIOSNT)
	LD	DE,ADRSLO
	ADD	HL,DE
	JP	(HL)
;
;  READ SECTOR
;
RDSEC:	LD	HL,(BIOSNT)
	LD	DE,RDSECO
	ADD	HL,DE
	JP	(HL)
;
;  WRITE SECTOR
;
WRSEC:	LD	HL,(BIOSNT)
	LD	DE,WRSECO
	ADD	HL,DE
	JP	(HL)
;
;  BDOS READ FILE SECTOR
;
READF:	LD	C,READ
	JP	BDOS
;
;  BDOS OPEN FILE
;
OPENF:	LD	C,OPEN
	JP	BDOS
;
;  DO SYSTEM TRACK
;
DOIT:	LD	HL,SYBUFR	;SET PTR
	LD	(BFRPTR),HL
DOTRK:	LD	C,1		;SET TRACK
	CALL	TRKSL
	LD	A,-1		;SET UP SECTOR CNT
	LD	(SECTOR),A
NXTSEC:	LD	A,(LSTSEC)	;IF LAST SECTOR THEN RETURN
	LD	HL,SECTOR
	INC	(HL)
	CP	(HL)
	RET	Z
	LD	E,(HL)
	LD	D,ZERO
	LD	HL,SECTBL	;SET SECTOR TABLE PTR
	LD	B,(HL)
	ADD	HL,DE
	LD	C,(HL)
	PUSH	BC
	CALL	SECSL
	POP	BC	;COMPUTE DELTA
	LD	A,C
	SUB	B
	CALL	AX128
	EX	DE,HL
	LD	HL,(BFRPTR)	;COMPUT PTR
	ADD	HL,DE
	LD	B,H
	LD	C,L
	CALL	ADRSL
	XOR	A
	LD	(RETRYS),A	;CLEAR RETRIES
RETRY:	LD	A,(RETRYS)	;IF RETRIES <10 THEN GO TO IT
	CP	10D
	JR	C,RETOK
	LD	HL,ERRM	;ELSE OUTPUT ERROR MSG
	CALL	EDITOR
	CALL	CONIN	;IF INPUT NOT RETURN THEN EXIT
	CP	CR
	JP	NZ,EXIT
	CALL	CRLF	;ELSE CONTINUE
	JR	NXTSEC
;
RETOK:	INC	A	;RETRIES := RETRIES +1
	LD	(RETRYS),A
	LD	A,(OPNFLG)	;IF FLAG = 0 THEN READ
	OR	A
	JR	Z,RD1
	CALL	WRSEC	;ELSE WRITE
	JR	ERRCHK
;
RD1:	CALL	RDSEC
ERRCHK:	OR	A	;IF NO ERRORS THEN CONTINUE
	JR	Z,NXTSEC
	JR	RETRY
;
;  MAIN PGM
;
START:	LD	SP,STACK
	LD	HL,SGNON	;OUTPUT SIGN-ON MSG
	CALL	EDITOR
	LD	A,(DEFFCB+1)	;IF NO FILENAME SPEC'D THEN NO
;				 OPEN
	CP	ASPACE
	JR	Z,GETSRC
	LD	DE,DEFFCB	;ELSE OPEN FILE
	CALL	OPENF
	INC	A	;IF NO ERR THEN SKIP 1ST 16 SECTORS
	JR	NZ,OPENOK
	LD	HL,NOSRCM	;ELSE OUTPUT NO SOURCE MSG
	CALL	ED1
	JP	EXIT
;
OPENOK:	XOR	A
	LD	(FCBCR),A	;READ FILE RECORD # 0
	LD	C,16D
WSTLP:	PUSH	BC
	LD	DE,DEFFCB
	CALL	READF
	POP	BC
	OR	A	;IF EOF THEN INCOMPLETE
	JR	NZ,INCOMP
	DEC	C	;DO UNTIL 16 DONE
	JR	NZ,WSTLP
	LD	HL,SYBUFR	;SET DMA ADDR TO BUFFER
RDNXTF:	PUSH	HL
	LD	B,H
	LD	C,L
	CALL	ADRSL
	LD	DE,DEFFCB	;READ NEXT
	CALL	READF
	POP	HL
	OR	A
	JR	NZ,GETDST
	LD	DE,128D	;BUFR PTR := BUFR PTR * 128D
	ADD	HL,DE
	JR	RDNXTF
;
INCOMP:	LD	HL,SCINCM	;OUTPUT SOURCE INCOMPLETE MSG
	CALL	ED1
	JP	EXIT
;
GETSRC:	LD	HL,SRCDKM	;OUTPUT SOURCE DRV MSG
	CALL	ED1
	CALL	CONIN
	CP	CR	;IF RETURN THEN NO READ
	JR	Z,GETDST
	SUB	'A'	;IF NOT 'A'-'C' THEN RESTART
	CP	4
	JR	C,SET1
	CALL	INVDRV
	JR	GETSRC
;
SET1:	ADD	'A'	;RESTORE DRIVE & PUT INTO MSG
	LD	(SRCDK),A
	SUB	'A'	;SELECT DRIVE
	CALL	DKSEL
	CALL	CRLF
	LD	HL,SRCDKP	;OUTPUT SOURCE DRV MSG
	CALL	EDITOR
	CALL	CONIN	;IF INPUT <> RETURN THEN RE-BOOT
	CP	CR
	JR	NZ,EXIT
	CALL	CRLF
	XOR	A
	LD	(OPNFLG),A	;SELECT READ OPERATION
	CALL	DOIT
	LD	HL,FNCCM	;OUTPUT FUNCTION COMPLETE MSG
	CALL	EDITOR
;
GETDST:	LD	HL,DSTDKM	;OUTPUT DEST DRV MSG
	CALL	ED1
	CALL	CONIN	;IF INPUT = RETURN THEN REBOOT
	CP	CR
	JR	Z,EXIT
	SUB	'A'	;IF NOT 'A'-'C' THEN RESTART
	CP	4
	JR	C,DESTOK
	CALL	INVDRV
	JR	GETDST
;
DESTOK:	ADD	'A'	;PUT DRV INTO MSG
	LD	(DSTDK),A
	SUB	'A'	;SET DRIVE
	CALL	DKSEL
	LD	HL,DSTDKP	;OUTPUT DEST PROMPT
	CALL	ED1
	CALL	CONIN
	CP	CR	;IF INPUT NOT RETURN THEN RE-BOOT
	JR	NZ,EXIT
	CALL	CRLF
	LD	HL,OPNFLG	;SET WRITE OPERATION
	LD	(HL),1
	CALL	DOIT
	LD	HL,FNCCM	;OUTPUT FUNCTION COMPLETE MSG
	CALL	EDITOR
	JR	GETDST
;
EXIT:	LD	A,ZERO
	CALL	DKSEL	;RESELECT DRV A
	CALL	CRLF
	JP	0
;
INVDRV:	LD	HL,INVDKM	;OUTPUT INVALID DRV MSG
	JP	ED1
;
;   MESSAGES
;
SGNON:	DB	'Jade DD SYSGEN  Ver 1.0',CR,LF
	DB	'(c) 1981 GRH Electronics, Cupertino, CA',0
;
SRCDKM:	DB	'Source drive name (or RETURN to skip)',0
;
SRCDKP:	DB	'Source on '
SRCDK:	DB	9D
	DB	' - Then type RETURN',0
;
DSTDKM:	DB	'Destination drive name (or RETURN to reboot)'
	DB	0
DSTDKP:	DB	'Destination on '
DSTDK:	DB	9D
	DB	' - Then type RETURN',0
;
ERRM:	DB	'PERMANENT ERROR, Type RETURN to ignore',0
;
FNCCM:	DB	'Function complete ',0
;
INVDKM:	DB	'INVALID DRIVE NAME (Use A,B,C or D)',0
;
NOSRCM:	DB	'No source file on disk',0
;
SCINCM:	DB	'Source file incomplete',0
;
;  VARIABLES
;
TRACK:	DB	0FFH	;TRACK #
SECTOR:	DB	0FFH	;SECTOR #
OPNFLG:	DB	0	;OPERATION FLAG (0=READ, 1=WRITE)
BFRPTR:	DW	SYBUFR	;RD/WR BUFFER PTR
RETRYS:	DB	0	;RD/WR RETRIES COUNT
;
	DS	32D
STACK:	EQU	$
;
	END
