;		NEW PASCAL BOOT MAINTENENCE PROGRAM
;
;BAD NEWS:  ALTHOUGH THE ORIGINAL "PGEN.ASM" FROM UCSD DOESN'T SAY "COPYRIGHT",
;  I HAVE DELETED SECTIONS OF THIS FILE IDENTICAL WITH THE UCSD ORIGINAL THAT
;   ARE NOT TRADITIONAL CP/M ROUTINES.  YOU'LL HAVE TO RESTORE THEM ON
;   YOUR OWN.  They are marked with asterisks in such a way that the file will
;   NOT assemble!...Jim Gagne, 21-Feb-80.
;NOTE THAT THIS PROGRAM REQUIRES THE DIGITAL RESEARCH OR MICROSOFT MACRO-
;  ASSEMBLER AND THE MACRO LIBRARY "MACRO.LIB" TO ASSEMBLE AT ALL.
;
;	THIS VERSION SUPPORTS THE DOUBLE DENSITY 512 BYTE SECTOR FORMAT
;VERSION OF THE UCSD PASCAL SYSTEM. PGEN NOW CONTAINS THE BOOTER FOR
;
;BOTH THE OLD AND NEW VERSIONS OF THE TARBELL FLOPPY DISK CONTROLLERS
;AS WELL AS THE DELTA CONTROLLER AND CROMEMCO 4FDC CONTROLLERS.
;THE PASCAL SYSTEM SUPPORTS 4 SEPARATE DISK FORMATS.
;
;  A.	SINGLE SIDE, SINGLE DENSITY, 26 128 BYTE SECTORS PER TRACK
;  B.	SINGLE SIDE, SINGLE DENSITY,  8 512 BYTE SECTORS PER TRACK
;  C.	SINGLE SIDE, DOUBLE DENSITY, 16 512 BYTE SECTORS PER TRACK
;  D.	DOUBLE SIDE, DOUBLE DENSITY, 16 512 BYTE SECTORS PER TRACK
;
;	THESE FORMATS GIVE THE FOLLOWING NUMBER OF BLOCKS PER DISK
;
;		A  -  494 BLOCKS
;		B  -  608 BLOCKS
;		C  - 1216 BLOCKS
;		D  - 2448 BLOCKS
;
;	PGEN OPERATION IS AS FOLLOWS: THE PROGRAM WILL ASK IF YOU WANT TO
;GET THE BOOTER. ANSWERING THIS REQUEST YES WILL CAUSE THE BOOTER ON TRACK
;ZERO OF DRIVE A TO BE READ INTO MEMORY, OTHERWISE THE SYSTEM ALREADY IN
;MEMORY WILL BE USED. THE PROGRAM WILL THEN ASK IF YOU WISH TO PUT THE
;BOOTER. ANSWERING YES WILL CAUSE THE BOOTER TO BE WRITTEN TO TRACK ZERO
;OF THE DISK IN DRIVE B (PASCAL #5:). IN ORDER FOR THE SYSTEM TO HANDLE
;A VARIETY OF DISK FORMATS IT IS NECESSARY FOR THE DISK TO HAVE A FORMAT
;CODE. THE CODE IS STORED AS THE LAST BYTE OF THE FIRST SECTOR OF TRACK 0.
;SEE THE BOOTER ASSEMBLY FOR DETAILS ON THE FORMAT CODE.
;	THE PROGRAM READS THE FORMAT CODE FROM THE DESTINATION DISK AND
;DISPLAYS THE DISK FORMAT ON THE CONSOLE. THE BOOTER IS THEN WRITTEN TO
;THE DESTINATION DISK WITH THIS CODE. IF THE DESTINATION DISK HAS NO
;FORMAT CODE THE PROGRAM WILL HALT AND REQUEST THAT THE FORMAT INFORMATION
;REQUIRED BE INPUT FROM THE CONSOLE BEFORE WRITING THE BOOTER TO THE DISK.
;THE WRITE PROCEDURE MAY BE REPEATED SEVERAL TIMES WITHOUT RELOADING
;THE PROGRAM BY ANSWERING YES TO THE REQUEST TO WRITE AGAIN.
;ON COMPLETION OF THE SYSTEM TRANSFER THE PROGRAM RETURNS TO CP/M.
;		CONSTRUCTION A NEW PGEN PROGRAM
;
;	PGEN MUST BE INITIALIZED FOR A SPECIFIC HARDWARE CONFIGURATION.
;THE PROGRAM IS IN TWO SEGMENTS, PGEN.ASM CONTAINS THE COLD BOOT LOADER
;AND THE CODE THAT COPIES THE SYSTEM TO THE DISK. BOOTER.ASM CONTAINS
;THE OLD PASCAL PINIT PROGRAM WHICH LOADS THE PASCAL INTERPRETER AND
;THE BIOS FOR THE SYSTEM. TO MODIFY THE SYSTEM FOR DIFFERENT TERMINAL
;DEVICES OR TO CHANGE THE SYSTEM SIZE IT IS NECESSARY TO REASSEMBLE
;BOOTER.ASM. BOOTER.ASM HAS MANY CONDITIONAL ASSEMBLY SWITCHES TO HANDLE
;A VARIETY OF TERMINALS, DISK CONTROLLERS AND TREMIINAL I/O CONTROLLERS.
;	AFTER REASSEMBLY THE BOOTER.HEX FILE MEST BE OVERLAYED ON PGEN
;USING SID OR DDT. THE OFFSET REQUIRED DEPENDS ON THE MEMORY SIZE AND
;THE SIZE OF THE BIOS. THE OFFSET FOR A 64K SYSTEM WITH A BIOS SIZE
;OF 1536 IS 1380H. THE OFFSET MAY BE OBTAINED BY TRIAL AND ERROR IF
;NECESSARY BY SIMPLY LOADING THE BOOTER.HEX FILE USING DDT AND VARIOUS
;OFFSETS. THE CORRECT OFFSET WILL CAUSE THE PROGRAM TO BE LOADED INTO
;MEMORY STARTING AT 980H. A SAMPLE LOAD SEQUENCE IS:
;
;		SID PGEN.HEX
;		IBOOTER.HEX
;		R1380
;		^C
;		SAVE 20 PGEN.COM
;Note added 21-Feb-80:	It is better to add to Booter, as I did, an
;  equate that figures the bias for you by the formula:  
;  PGENBIAS EQU	980H + (64 * 1024) - BOOTERLOC ;BOOTERLOC = start of BOOTER
;Then simply read the listing for the correct value.	Jim Gagne
;
;
	MACLIB	MACRO			;INCLUDE MACROS
FALSE	EQU	00H
TRUE	EQU	NOT FALSE
;
C4FDC	EQU	FALSE			;CONDITIONAL FOR CROMEMCO
;
;
MSIZE	EQU	64			;MEMORY SIZE IN KBYTES
BIOSSZ	EQU	1536
TPA	EQU	100H
BDOS	EQU	5
RDCON	EQU	1
WRBUF	EQU	9
START	EQU	900H
FBYTE	EQU	97FH			;DISK FORMAT BYTE LOCATION
ENDPT	EQU	START+128+256+768+BIOSSZ	;BOOT+PINIT+SPARE+BIOS
NSECTS	EQU	20
FSTSCT	EQU	1
RDFLG	DB	0			;INDICATES BOOTER READ FROM DISK
FMFLG	DB	0			;INDICATES FORMAT FLAG ON DEST DISK
;
;
;
	ORG	TPA
;
;
	LXI	SP,STACK
MAIN:
	PRINT	<CR,LF,LF,'        PASCAL SYSTEM GENERATION PROGRAM VERS 2.0'>
	IF	C4FDC
	PRINT	<CR,LF,LF,'             CROMEMCO 4FDC AND PERSCI VERSION'>
	ENDIF
	PRINT	<CR,LF,LF>
	CALL	GET$BOOTER
	CALL	PUT$BOOTER
	JMP	REBOOT
;
;
HOME:				;HOME DISK
	LHLD	1
	MVI	L,18H
	PCHL
;
SELDSK:				;SELECT DISK
	LHLD	1
	MVI	L,1BH
	PCHL
;
SETSECT:			;SET SECTOR
	LHLD	1
	MVI	L,21H
	PCHL
;
SETDMA:				;SET DMA ADDRESS
	LHLD	1
	MVI	L,24H
	PCHL
;
READ:				;READ A SECTOR
	LHLD	1
	MVI	L,27H
	PCHL
;
WRITE:				;WRITE A SECTOR
	LHLD	1
	MVI	L,2AH
	PCHL
;
;
GET$BOOTER:			;MAYBE A BOOTER COMES IN
	PRINT	<CR,LF,LF,'GET BOOTER (Y/N) '>
	CHARIN
	CPI	'Y'
	RNZ			;RETURN IF NOT YES
	PRINT	<'READING BOOTER FROM DRIVE A, TYPE RETURN '>
	CHARIN
	CPI	3		;IS IT CONTROL C
	JZ	MAIN
	MVI	A,0FFH
	STA	RDFLG		;SET FLAG
	CALL	DO$READ
	RET			;DONE
;
;
PUT$BOOTER:			;DOES THE BOOTER GO OUT?
	PRINT	<CR,LF,'PUT BOOTER (Y/N) '>
	CHARIN
	CPI	3		;CONTROL C
	JZ	MAIN
	CPI	'Y'
	RNZ			;EXIT IF NO
PUT$AGAIN:			;ELSE START TO PUT
	PRINT	<CR,LF,'WRITING BOOTER TO DRIVE B, TYPE RETURN '>
	CHARIN
	CPI	3		;CHECK FOR CONTROL C
	JZ	MAIN
	CALL	READ$FMT		;READ T 0 S 1 FROM DESTINATION DISK
	CALL	MOVE$BOOT
	PRINT	<CR,LF,'THE DESTINATION DISK FORMAT IS - '>
	CALL	WRITE$FMT
	LDA	FMFLG		;CHECK IF KNOWN FORMAT
	ORA	A
	JNZ	PA1
	CALL	READ$FMT
PA1:	CALL	DO$WRITE	;NOW PUT IT OUT
	PRINT	<CR,LF,LF,'AGAIN (Y/N) '>
	CHARIN
	CPI	'Y'
	JZ	PUT$AGAIN	;WRITE IT AGAIN
	RET			;ALL DONE
;
;
REBOOT:				;PULL BACK CP/M
	PRINT	<CR,LF,LF,'REBOOTING CP/M, TYPE RETURN '>
	CHARIN
	MVI	C,0
	CALL	SELDSK		;SELECT DRIVE 0
	JMP	0
;
DO$READ:			;READ IN THE BOOTER
*****************************************************************
*	Sorry, you'll have to copy this from the UCSD original.	*
*	5 lines, unchanged.					*
*****************************************************************
DR$LOOP:				;THEN PUT IT OUT
*****************************************************************
*	Sorry, you'll have to copy this from the UCSD original.	*
*	18 lines, unchanged.					*
*****************************************************************
;
;
DO$WRITE:			;WRITE OUT THE BOOTER
	MVI	C,1		;SELECT THE DISK
	CALL	SELDSK
	CALL	TIME
	CALL	HOME
	CALL	TIME
	LXI	B,START
	LXI	D,NSECTS SHL 8 + FSTSCT
DW$LOOP:			;ALL PARAMS SET - RUN IT OUT
*****************************************************************
*	Sorry, you'll have to copy this from the UCSD original.	*
*	18 lines, unchanged.					*
*****************************************************************
;
MLOOP:	LDAX	D		;GET A BYTE
	MOV	M,A		;STORE IT
	INX	H
	INX	D		;INCR POINTERS
	DCR	C		;BYTE COUNT
	JNZ	MLOOP
	MVI	A,0C7H		;RESTART ZERO INSTRUCTION
	STA	97DH		;PUT IT IN BUFFER TOO
	RET
;
GET$FORMAT:			;READ DISK FORMAT FROM CONSOLE AND SET FBYTE
	PRINT	<CR,LF,'IS DISK SINGLE DENSITY? (Y/N) '>
	CHARIN
	CPI	'Y'
	MVI	A,20H		;SINGLE DENSITY CODE
	JZ	GF2
	MVI	A,10H		;DOUBLE DENSITY CODE
GF2:	STA	FBYTE		;SAVE IN FBYTE
	PRINT	<CR,LF,'DOES DISK HAVE 128 BYTE SECTORS? (Y/N) '>
	CHARIN
	CPI	'Y'
	MVI	B,0		;128 BYTE CODE
	JZ	GF4
	MVI	B,2		;512 BYTE CODE
GF4:	LDA	FBYTE
	ORA	B		;OR IN THE BYTE CODE
	STA	FBYTE
	RET
;
READ$FMT:			;READ FORMAT CODE FROM DESTINATION DISK
	MVI	C,1		;SELECT THE DISK
	CALL	SELDSK
	CALL	TIME
	CALL	HOME
	CALL	TIME
	LXI	B,START
	CALL	SETDMA
	LXI	B,1
	CALL	SETSECT		;SECTOR 1
	CALL	READ		;READ DRIVE B TRACK 0 SECTOR 1
	RET
;
WRITE$FMT:			;DECODE FORMAT BYTE AND DISPLAY
	MVI	A,0FFH
	STA	FMFLG		;SET FLAG TO KNOWN FORMAT
	LDA	FBYTE
	CPI	20H
	JNZ	WF2
	PRINT	<'SINGLE DENSITY 128 BYTE SECTORS',CR,LF>
	RET
WF2:	CPI	22H
	JNZ	WF4
	PRINT	<'SINGLE DENSITY 512 BYTE SECTORS',CR,LF>
	RET
WF4:	CPI	12H
	JNZ	WF6
	PRINT	<'DOUBLE DENSITY 512 BYTE SECTORS',CR,LF>
	RET
WF6:	PRINT	<'NO FORMAT CODE ON DISK',CR,LF>
	XRA	A
	STA	FMFLG		;SET FLAG FOR NO FORMAT
	RET
;
TIME:	LXI	B,3000H		;TIMING DELAY
DELAY:	DCX	B
	MOV	A,B
	ORA	C
	JNZ	DELAY
	RET
;
;
;
;
;		PASCAL BOOT LOADER
;
;THIS IS A MODIFICATION OF TARBELL'S BOOT LOADER DESIGNED TO RUN AT 0H
;THE CODE IS MOVED TO 900H BY PGEN WITH THE PROPER FORMAT CODE IN THE
;LAST BYTE FOR WRITING ON THE SYSTEM TRACK OF A PASCAL DISK.
;THE PROGRAM LOADS 20 SECTORS FROM DISK WHEN EXECUTED STARTING WITH
;TRACK 0 SECTOR 2.
;
;
	IF	C4FDC
DISK	EQU	30H
	ELSE
DISK	EQU	0F8H		;BASE ADDR FOR DISK I/O PORTS
	ENDIF
DCOM    EQU	DISK
DSTAT   EQU	DISK
TRACK   EQU	DISK+1
SECT    EQU	DISK+2
DDATA   OQU	DISK+3
WAIT    EQU	DISK+4
LOADP	EQU	MSIZE*1024-BIOSSZ-1024
NSECTS	EQU	20		;NUMBER OF SECTORS TO LOAD
;
	IF	C4FDC
OFFSET	EQU	80H		;BOOT OFFSET FOR CROMEMCO PROM
	ELSE
OFFSET	EQU	00H		;BOOT OFFSET FOR OTHER SYSTEMS
	ENDIF
;
;
;
	IF	C4FDC
BOOT:	MVI	A,01
	OUT	40H
	ELSE
BOOT:   LXI	SP,100H
	ENDIF
	LXI	B,2		;B=TRACK,  C=SECTOR
	MVI	D,NSECTS	;D CONTAINS SECTOR COUNT
	LXI	H,LOADP		;STARTING LOAD ADDR FOR PROGRAM
	MOV	A,B
        OUT	DDATA
	MVI	A,1FH		;SEEK - 10MSEC STEP RATE NO HEAD LOAD OR VERIFY
	OUT	DCOM		;SEEK TRACK 0
LOOP1:	IN	WAIT
	IF	C4FDC
	RAR
	JNC	LOOP1-BOOT+OFFSET	;WAIT FOR INTRQ
	ELSE
	ORA	A
	MVI	A,1
	JM	ERROR-BOOT+OFFSET
	ENDIF
        IN 	DSTAT
      	ANI  91H
        JNZ  ERROR-BOOT+OFFSET
        MOV  A,C
        CALL READ0-BOOT+OFFSET
RBLK1:  JNZ  ERROR-BOOT+OFFSET
      	DCR  D
	JZ   LOADP
        INR  C
RBLK2:  MOV  A,C
	CALL	READ1-BOOT+OFFSET
	JMP	RBLK1-BOOT+OFFSET
;
;
READ1:	OUT	SECT
	IN	DSTAT
        RRC
	MVI	A,1
	JC	RERR-BOOT+OFFSET
	MVI	A,88H
	JMP	READE-BOOT+OFFSET
;
READ0:	OUT	SECT
	IN	DSTAT
        RRC
        MVI  A,1
        JC   RERR-BOOT+OFFSET
        MVI  A,8CH
	IF	C4FDC
READE:	PUSH	PSW
	MVI	A,0B1H		;TURN ON AUTOWAIT, SELECT 0
	OUT	WAIT
	POP	PSW
	OUT	DCOM
	ELSE
READE:  OUT  DCOM
	ENDIF
RLOOP:	IN	WAIT
	IF	C4FDC
	RAR
	JC	RDONE-BOOT+OFFSET
	ELSE
	ORA	A
	JP	RDONE-BOOT+OFFSET
	ENDIF
        IN   DDATA
        MOV  M,A
        INX  H
        JMP  RLOOP-BOOT+OFFSET
;
RDONE:  IN   DSTAT
RERR:   ANI  9DH
        RET
;
;
ERROR:  CMA
	OUT	0FFH
ENDBOOT:HLT
	DS	128
STACK:	EQU	$
;
	END
