;			ZB4MHZ.ASM

;		P. L. Kelley (617) 332-1610
;			 05/24/82

;****WARNING**** Read the text of this file before using. ****WARNING****

;Converts ZBIOS.SYS and ZFOR.COM to operate with a 4 MHz CPU on the H89
;using the Percom disk controller. Note that single density soft sectored
;disks and hard sectored disks cannot be cold booted at 4 MHz with Percom's
;rom.

TRUE		EQU	-1
FALSE		EQU	NOT TRUE

;You will want to convert this into two files:

;	1. The present version of this file

;	2. A file called ZF4MHZ.ASM made by reversing TRUE and FALSE
;	   in the equates which follow

ZB4MHZ	EQU	TRUE	;makes ZB4MHZ.ASM/HEX, set FALSE for ZF4MHZ.ASM/HEX
ZF4MHZ	EQU	FALSE	;set TRUE to make ZF4MHZ.ASM/HEX


;set the following to FALSE if no parallel printer

PARALLEL 	EQU	TRUE


;This program is set up for version 1.00 of Percom's ZBIOS.SYS and
;ZFOR.COM. If you have another version you will likely need to
;change the values of BLSTLOC, FCOUNT, and the various HDLYs and
;INTDLYs.

;After you overlay the memory image of ZBIOS.SYS with ZB4MHZ.HEX do:
;	SAVE 23 ZBIOS.SYS

;ZB4MHZ does two things:

;	1. Allows operation with a 4MHz CPU

;	2. Operates a Centronics 730 parallel printer as follows:
;		a. Handles formfeed
;		b. Assumes auto linefeed after carriage return


;After you overlay the memory image of ZFOR.COM with ZF4MHZ.HEX do:
;	SAVE 9 ZFOR.COM

;ZF4MHZ allows operation of ZFOR.COM with a 4 MHz CPU.


TPA	EQU	0100H	;location of start of ZBIOS.SYS when loaded by DDT

BPATCH	EQU	1600H	;area for patching located above
			;distribution version of ZBIOS.SYS

FPATCH	EQU	0898H	;area for patching ZFOR.COM located at
			;lowest memory reserved for stack
			;i.e. assume area reserved for stack in
			;distribution version is longer than necessary
	
BLSTLOC		EQU	02BEH
BHDLY1		EQU	0B9EH
BHDLY2		EQU	0BA6H
BHDLY3		EQU	0C70H
BHDLY4		EQU	0C93H
BHDLY5		EQU	0CDAH
BINTDLY		EQU	0D14H

FHDLY1		EQU	0608H
FHDLY2		EQU	0623H
FCOUNT		EQU	0752H
FHDLY3		EQU	075FH
FINTDLY1	EQU	07E5H
FINTDLY2	EQU	0811H

DPORT		EQU	0E0H	;printer data port
TPORT		EQU	0E5H	;port to test for printer status
BUSY		EQU	020H	;busy bit

;change the following to suit your system size

SZ64K		EQU	TRUE
SZ48K		EQU	FALSE
SZ32K		EQU	FALSE

;end of system size choice

	
	IF	SZ64K

BIOS	EQU	0E800H	;start of BIOS for 64K

	ENDIF	;SZ64K

	
	IF	SZ48K

BIOS	EQU	0A800H

	ENDIF	;SZ48K


	IF	SZ32K

BIOS	EQU	6800H

	ENDIF	;SZ32K


	IF	ZB4MHZ

PATCH	EQU	BPATCH+TPA
OFFSET	EQU	BIOS-TPA

	ENDIF	;ZB4MHZ


	IF	ZF4MHZ

PATCH	EQU	FPATCH
OFFSET	EQU	0

	ENDIF	;ZF4MHZ


	IF	ZB4MHZ AND PARALLEL

	ORG	BLSTLOC+TPA	;location to patch to jump to parallel
				;printer routine

	JMP	PARPRINT

	ENDIF	;ZB4MHZ AND PARALLEL



	IF	ZB4MHZ


;the next five changes take care of hard disk timing in ZBIOS

	ORG	BHDLY1+TPA

	MVI	A,28H		;2X previous value


	ORG	BHDLY2+TPA

	MVI	A,20H		;2X previous value


	ORG	BHDLY3+TPA

	MVI	A,28H		;2X previous value


	ORG	BHDLY4+TPA

	MVI	A,28H		;2X previous value


	ORG	BHDLY5+TPA

	MVI	D,0F0H		;3X previous value


	ORG	BINTDLY+TPA	;location to modify ZBIOS.SYS
				;to extend the delay loop between the force
				;interrupt command and a type I command
				;*** this is crucial ***

	JMP	EXINTDLY	;delay routine in patch area
	NOP			;eliminate odd XTHL


	ENDIF	;ZB4MHZ



	IF	ZF4MHZ


;The next four fix hard disk timing in ZFOR.COM

	ORG	FHDLY1

	MVI	A,3		;3X the previous value


	ORG	FHDLY2

	MVI	A,3		;3X the previous value


	ORG	FCOUNT

	LXI	D,0480H		;the previous value was 036DH
				;it was found that doubling this
				;value would not give properly
				;formatted hard sectored disks

	ORG	FHDLY3

	MVI	A,28H		;2X the previous value


;The next two changes fix interrupt delay timing in ZFOR.COM


	ORG	FINTDLY1

	CALL	EXINTDLY
	NOP


	ORG	FINTDLY2

	CALL	EXINTDLY
	NOP

	ENDIF	;ZF4MHZ



	ORG	PATCH


EXINTDLY	EQU	$+OFFSET
	MVI	A,0BH		;delay count
DELAY		EQU	$+OFFSET
	DCR	A
	JNZ	DELAY		;loop until delay finished

	IF	ZB4MHZ

	CALL	BINTDLY+BIOS+3	;go back to output command
	PUSH	H		;delay just a bit for
	POP	H		;single density soft sectored disks

	ENDIF	;ZB4MHZ

	RET


	IF	ZB4MHZ AND PARALLEL

PARPRINT	EQU	$+OFFSET
	IN	TPORT
	RAR
	RAR
	RNC		;return	if printer is not connected
PBUSY	EQU	$+OFFSET
	IN	TPORT
	ANI	BUSY	;printer busy?
	JNZ	PARPRINT		;loop if printer busy
	MOV	A,E	;character in register E on entering routine
	CPI	80H	;test for non printable character
	RNC		;return if non printable
	CPI	20H	;test for not control character
	JNC	CHAR
	CPI	0AH	;test for linefeed
	JZ	LFEED
	CPI	0CH	;test for formfeed
	JZ	FFEED
	CPI	0DH	;test for carriage return
	JZ	CARET
	RET		;return if any other control character
			;i.e. present version does not allow
			;elongated characters
CHAR	EQU	$+OFFSET
	LXI	H,CRFLG	;point to cr flag
	MVI	M,00H	;reset cr flag
	INX	H	;point to crlf flag
	MVI	M,00H	;reset crlf flag
OUTPUT	EQU	$+OFFSET
	OUT	DPORT	;print character
	RET

CARET	EQU	$+OFFSET
	CALL	INCLN	;call line # increment routine
	LXI	H,CRFLG	;load carriage return flag
	MVI	A,01H	;load the value of the CR and CRLF flags
			;when set
	CMP	M	;test for CR flag already set
	JZ	CRLFRP	;jump to output LF if set
	MVI	M,01H	;set carriage return flag
	INX	H	;point to CRLF flag
	CMP	M	;test if flag set
	JZ	RCRLFF	;jump to reset CRLF flag and output LF
			;otherwise output CR
RELOAD	EQU	$+OFFSET
	MOV	A,E	;restore character
	JMP	OUTPUT

CRLFRP	EQU	$+OFFSET
	MVI	A,0AH	;load LF
	JMP	OUTPUT

RCRLFF	EQU	$+OFFSET
	MVI	M,00H	;reset CRLF flag
	JMP	CRLFRP	;jump to output LF

INCLN	EQU	$+OFFSET
	LXI	H,PAGEL	;point to page length
	MOV	A,M	;load page length into A
	INX	H	;point to line #
	INR	M	;increment line #
	CMP	M	;compare page length to line #
	JZ	NEWPG	;jump if new page
	RET

NEWPG	EQU	$+OFFSET
	MVI	M,00H	;new page
	RET

LFEED	EQU	$+OFFSET
	LXI	H,CRFLG	;point to CR flag
	MVI	A,00H	;load CR flag reset value
	CMP	M	;compare with flag
	JNZ	LFRST	;jump if line feed follows carriage return
	CALL	INCLN	;call line # increment routine
	JMP	RELOAD	;output LF

LFRST	EQU	$+OFFSET
	MVI	M,00H	;reset CR flag
	INX	H	;point to CRLF flag
	MVI	M,01H	;set CRLF flag
	RET		;don't output anything

FFEED	EQU	$+OFFSET

;The Centronics 730 does not respond to formfeed (0CH).
;Instead of linefeeds this routine outputs a space followed by
;a carriage return to prevent the ribbon from lifting above the
;print head when too much vertical paper motion occurs. The
;problem occurs with tractor feed paper.

	MVI	E,' '	;load a space
	CALL	PBUSY	;output a space
	PUSH	H	;give time
	POP	H	;     for BUSY
	PUSH	H	;	  signal to
	POP	H	;		turn on
	MVI	E,0DH	;load CR
	CALL	PBUSY	;output CR
	LXI	H,LINEN	;point to line #
	MVI	A,00H	;top of page line #
	CMP	M	;test for top of page
	RZ		;return if at top
	JMP	FFEED	;otherwise repeat

PAGEL	EQU	$+OFFSET
	DB	42H	;page length

LINEN	EQU	$+OFFSET
	DB	02H	;initial line #
			;the print head is two lines down when
			;the paper tear line is at the tear bar

CRFLG	EQU	$+OFFSET
	DB	00H,01H	;initial CR and CRLF flag values

	ENDIF	;ZB4MHZ AND PARALLEL


	END