; DATE 00/00/00  (0:04  last revision
;
; SIG/M release version WYSE200 set to FALSE, CLOCK set TRUE for Compupro
; system support clock routine.
;

	TITLE	'A WORDMASTER SPECIAL WyseWord'

;
; DATE 10/05/83 18:13
; by: H.M. Van Tassell, 120 Hill Hollow Rd, Watchung NJ 07060 (201)755-5372
;
; PATCHS WM FOR 2 BYTE SEQUENCE KEYS, PROGRAMS  FCN KEYS, AND TIME STAMPS
;
; THE PATCH FOR TIME STAMPING USES THE COMPUPRO SYSTEM SUPPORT CLOCK
; ROUTINE. YOU MUST SUPPLY YOUR OWN CLOCK ROUTINE OR SET THE CLOCK
; EQUATE TO FALSE
;
; TO USE YOU MUST START FILE WITH "; DATE <-16 SPACES-> "
; IT IS NECESSARY THAT DATE START AT THE THIRD LOCATION ON
; THE FIRST LINE WITH 16 OR MORE FOLLOWING SPACES
;
; THE PATCH WAS WRITTEN TO PROGRAM THE FUNCTION KEYS ON THE WYSE-200
; OR TO USE ON  WYSE-100 WITH THE WYSEWORD FIRMWARE (PROM) INSTALLED.
; YOU MAY FIND THE ROUTINES HELPFUL IF YOUR TERMINAL TERMINAL HAS
; PROGRAMABLE FUNCTION KEYS.
;
; THERE IS A ROUTINE TO 'RE-PROGRAM' WORDMASTER TO ALLOW IT TO RESPOND
; TO TWO BYTE SEQUENCES THAT MANY TERMINALS USE FOR SPECIAL FUNCTION KEYS
; IT IS USED HERE TO ALLOW USE OF THE SPECIAL WordStar SEQUENCES THAT THE
; WYSEWORD USES, BUT IT CAN BE USED FOR ESCAPE SEQUENCES WITH LITTLE CHANGE.
;
; LOOK THROUGH THE PATCH AND REVISE AS NECESSARY TO FIT YOUR NEEDS.
;
;FOR WORDMASTER VERSION 1.07 AND WYSE-100/200 TERMINAL-SEE EQUATE
;FIRST VERSION 06/12/83 BY H.M.VAN TASSELL
; 
; TO USE JUST ASSEMBLE PATCH AND OVERLAY THE WORDMASTER COM FILE
; USING DDT.
;>>>>>>>>>>> be sure to save enough pages when patch is applied <<<<<<<<<<

FALSE	EQU	0
TRUE	EQU	NOT FALSE

CLOCK	EQU	TRUE		;SET TRUE FOR RDTIME ROUTINE

WYSE200	EQU	FALSE		;USE FALSE FOR WYSE-100

REV	EQU	7		;REVISION NUMBER

BDOS	EQU	0005H		;BDOS CALL
ESC	EQU	1BH
LF	EQU	0AH
CR	EQU	0DH
DEL	EQU	7FH
PRSTR	EQU	09H		;PRINT STRING ENDING WITH $

SIGN1:	EQU	167H		;FIRST SIGNON MESSAGE
SIGN2:	EQU	106H		;SECOND SIGNON MESSAGE

OUTCHR:	EQU	01EFH		;WM-SEND OUT CHAR

CLSSCRN: EQU	0180H		;BEGIN CLEAR SCREEN ROUTINE-6 NOP
TCURSOR: EQU	0196H		;POSITION CURSOR ROUTINE
EREOL:	EQU	01BBH		;ERASE TO END OF LINE CHAR
NOVIO:	EQU	01BDH		;PUT 0FFH HERE FOR NO VIO
DELCLR:	EQU	01C1H		;START OF DELAY BYTES IN MS (19H)

PBEGMEM: EQU	01B7H		;WM BEGIN OF DATA MEMORY
NORJMP:	EQU	0269H		;WM NORMAL JMP AT 100H
PATCH:	EQU	23B6H		;PATCH WM AT THIS ADDR TO NEW PATCH
BEGIN:	EQU	29B8H		;WM OLD BEGIN DTAT MEMORY

DIRECT:	EQU	23C7H		;WM ROUTINE FOR DIRECT BIOS CALLS

LENDAT:	EQU	15		;LENGTH OF DATE STRING
CDATE:	EQU	001DH		;ADDRESS OF CALL TO LOCATE DATSTR
CHOUT:	EQU	24FCH		;ROUTINE WHERE PROBE WAS PLACED
PROBE:	EQU	04E0H		;PLACE TO PUT JMP TO DATE PATCH
RET1:	EQU	04E3H		;RETURN HERE IF NOTHING DONE
RET2:	EQU	04DEH		;RETURN HERE IF SOMETHING DONE

	IF	WYSE200
	ORG	100H		;PATCH JUMP TO LABEL ROUTINE
	JMP	LABELS
	ENDIF	;WYSE200
	IF  NOT WYSE200
	ORG	100H
	JMP	NORJMP
	ENDIF	;NOT WYSE200

	ORG	PBEGMEM		;PATCH IN NEW BEGIN MEM
	DW	BEGBUFF		;TO START AT END OF PATCH

	IF	CLOCK
	ORG	PROBE		;DATE STAMP PATCH
	JMP	DAPATCH
	ENDIF	;CLOK

	ORG	SIGN2		;GET RID OF COMMERICAL 
	DB	0

	ORG	SIGN1		;NEW SIGN ON MESSAGE
	DB	'@'+REV 	;REVISION LETTER AFTER VERSION
	IF	WYSE200
	DB	' WYSE-200'
	ELSE
	DB	' WYSE-100'
	ENDIF	;WYSE200
	DB	' WordStar keys'
	DB	0DH,0AH

	ORG	CLSSCRN		;CLEAR SCREEN ROUTINE
	DB	0,0,0,0,0,0	;TO KEEP CONCOMPATIBILITY
	MVI	A,1AH		;^Z CLEARS SCREEN
	CALL	OUTCHR		;SEND IT
	RET

	ORG	TCURSOR		;POSITION CURSOR ROUTINE
	MVI	A,ESC		;FIRST AN ESCAPE
	CALL	OUTCHR
	MVI	A,'='		;THEN AN '="
	CALL	OUTCHR
	MVI	A,' '		;OFFSET
	ADD	L
	CALL	OUTCHR		;SEND ROW NUMBER
	MVI	A,' '
	ADD	H
	CALL	OUTCHR		;AND SEND COLUMN
	RET			;ALL DONE

	ORG	EREOL		;ERASE TO END OF LINE CHAR
	DB	ESC,'T'
	
	ORG	NOVIO		;NO VIO BOARD
	DB	0FFH

	ORG	DELCLR		
	DB	0		;DELAY WHILE CLERING SCREEN
	DB	0		;DELAY WHILE POSITION CURSOR
	DB	0		;DELAY WHILE EREOL

;IN WM STARTING AT 11C5H THERE IA A 2BYTE OFFSET TABLE FOR
;EACH CTRL CHR-SOME OF THESE WE WILL PATCH TO CHANGE THE
;ACTION OF THE CTRL CHRS.


	ORG	11DDH		;^L DO 4 TIMES
	DW	1345H		;WAS ^@

	ORG	1150H		;LOAD CTRL KEY FOR 4 TIMES
	DB	0CH		;MUST MATCH 

	ORG	11EFH		;^U INTERRUPT
	DW	23EBH		;WAS 14BF

	ORG	11F1H		;^V INSERT TOGGLE
	DW	150BH		;WAS 1345

	ORG	239DH		;DISABLE VIO
	DB	0FFH		;WAS 16

	ORG	11FDH		;^\ DELETE LINE LEFT
	DW	14BFH		;WAS 1460

	ORG	11FFH		;^] DELETE LINE RIGHT
	DW	14DDH		;WAS 151A

;IN WM STARTING AT 10D6H THERE IS A 1 BYTE OFFSET TABLE FOR
;EACH CTRL CHR WHICH SETS THE PRIORITY OF THE ACTION CAUSED BY
;THE CTRL KEY AND SHOULD BE KEEP SAME IF CTRL KEY 2 BYTE OFFSET
;TABLE IS CHANGED

	ORG	10EDH		;CORRECT ^W BUG
	DB	80H


;NOW PUT IN PATCH TO TRANSLATE THE 2 BYTE WYSEWORD COMMANDS TO
;SINGLE CHAR WORD MASTER COMMANDS.

	ORG	PATCH		;PATCH-OUT WM DIRECT CONIN
	CALL	START		;CALL AND SUBSTITUTE THIS PATCH


	ORG	BEGIN		;PATCH IS LOCATED AT OLD BEGIN MEM
START:
;  GET FIRST CHAR INTO REG A
	PUSH	B		;PUSH REG ETC, SAME
	PUSH	D		;AS WM DIRECT CALL
	PUSH	H
	LXI	H,1FCCH
	PUSH	H
	CALL	CONIN 		;USE DIRECT BIOS CALL

;  CHECK IF FIRST CHAR IN REG A IS IN THE CTRL CHAR CHECK TABLE
	LXI	H,FCTABLE	;HL=>FIRST CHAR CHECK TABLE
FCHAR:	PUSH	PSW
	MOV	A,M
	ORA	A		;IS ENTRY A ZERO-END OF TABLE
	JNZ	FC1		
	POP	PSW		;YES-RETURN TO WM
	RET
FC1:	POP	PSW
	CMP	M		;IS ENTRY=FIRST CHAR
	JZ	FC2
	INX	H		;NO-BUMP TO NEXT
	INX	H		;ENTRY AND TRY AGAIN
	INX	H
	JMP	FCHAR
FC2:				;YES GET XLATE TABLE ADDR
	INX	H		;BUMP TO XLATE TABLE
	MOV	E,M		;LSB
	INX	H
	MOV	D,M		;MSB
	PUSH	D		;DE=>XLATE TABLE FOR FIRST CHAR

;  DELAY TO LET ALL CHAR LEAVE TERMINAL
 	CALL	DELAY

;  GET SECOND CHAR INTO REG A - THE FIRST CTRL CHAR WILL BE LOST
	CALL	CONIN 

; TRANSLATE SECOND CHAR IF ITS IN FIRST CHAR'S XLATE TABLE
	POP	H		;HL=>FIRST CHAR'S XLATE TABLE
SCHAR:	PUSH	PSW
	MOV	A,M		
	ORA	A		;IS ENTRY A ZERO-END OF TABLE
	JZ	NOXLAT		;YES
	POP	PSW
	CMP	M		;IS ENTRY=SECOND CHAR
	JZ	XLATE
	INX	H		;NO-TRY AGAIN
	INX	H
	JMP	SCHAR


NOXLAT:	;NO TRANSLATION EXCEPT CHANGE TO NUL IF CTRL CHAR
	POP	PSW
	CPI	' '		;IS SECOND CHAR >= SPACE
	RNC			;YES RETURN TO WM
	MVI	A,0		;ELSE SUBSTITUTE A NUL
	RET			;AND RETURN TO WM

XLATE:	;MAKE TRANSLATION PER APPROPATE XLATE TABLE VALUE
	INX	H		;BUMP TO CHAR FOR TRANSLATION
	MOV	A,M		;INTO REG A
	RET 			;AND RETURN TO WM

CONIN:	;DIRECT BIOS CALL
	MVI	A,6		;OFFSET FROM WBOOT TO CONIN
	LHLD	0001		;GET BIOS WBOOT
	ADD	L		;ADD OFFSET
	MOV	L,A
	PCHL			;JMP TO IT

DELAY:	LXI	B,20  		;DELAY LENGTH IN MS
DLAY1:	MVI	A,5*1000/26	;CPU SPEED=5 MH 
DLAY2:	DCX	B
	INX	B
	DCR	A
	JNZ	DLAY2		;IF NOT 1 MS
	DCX	B
	MOV	A,C
	ORA	B
	JNZ	DLAY1
	RET


FCTABLE	;3-BYTE TABLE FOR CHECKING FIRST CHAR
	DB	'K'-40H		;IF FIRST CHAR IS ^K
	DW	KTABLE		;USE KTABLE FOR XLATE
	DB	'O'-40H
	DW	OTABLE
;	DB	'P'-40H		;DONT USE PTABLE
;	DW	PTABLE
	DB	'Q'-40H
	DW	QTABLE
	DB	0		;END OF TABLE

KTABLE 	;XLATE TABLE IF FIRST CHAR IS CTRL K
	DB	0  		;END OF TABLE

OTABLE 	;XLATE TABLE IF FIRST CHAR IS CTRL O
	DB	'X','V'-40h	;S-INS REP=INS
	DB	'I','I'-40h	;SET TAB=TAB
	DB	'N','Q'-40h	;SET TAB/S=RT TAB STOP
	DB	'R','L'-40h	;SCRN EDIT=X4
	DB	'L','L'-40h	;SCRN EDIT/S=X4
	DB	0  		;END OF TABLE

;PTABLE	;XLATE TABLE IF FIRST CHAR IS CTRL P
;	DB	0		;END OF TABLE

QTABLE 	;XLATE TABLE IF FIRST CHAR IS CTRL Q
	DB	'Y',']'-40H	;LINE ERASE=EOL
	DB	7FH,'\'-40H	;RUBOUT/S=EBOL
	DB	'E','^'-40h	;HOME=TOP/BOT
	DB	 05,'^'-40H	;UP KEY/S=T/B
	DB	'X','^'-40h	;DN ARROW/S=T/B
	DB	'C','^'-40H	;SCRL UP/S
	DB	'R','^'-40h	;SCRL DN/S
	DB	'S','B'-40h	;LEFT ARROW/S=L/R
	DB	'D','B'-40H	;RT ARROW/S
	DB	0  		;END OF TABLE

	IF	CLOCK
DAPATCH: ; THIS IS THE DATE AND TIME PATCH
	CALL	CHOUT
	PUSH	PSW
	LDA	FIRST		;IS THIS FIRST TIME THROUGH
	ORA	A
	JZ	ININIT		;YES GO TO IT
	POP	PSW
RT1:	JMP	RET1		;NO RETURN NOTHING DONE

; INIT LOOKS AT TEXT BUFFER AND IF IT FINDS DATE IT UPDATES
; WITH CURRENT DATE & TIME

ININIT:	PUSH	B
	PUSH	D
	PUSH	H

	CALL	INIT

	POP	H
	POP	D
	POP	B
	POP	PSW
RT2:	JMP	RET2


INIT:	MVI	A,0FFH
	STA	FIRST		;SET FIRST TIME FLAG
	LXI	D,VERTXT	;POINT TO TEXT AREA VER. MESSAGE
	LXI	H,VMES		;POINT TO STD. VERSION MESSAGE
	MVI	C,VMLEN		;LENGTH TO COMPARE
	CALL	COMPAR
	JZ	RDTIME		;GO DO UPDATE
	LHLD	RT1+1		;CHANGE RET JUMP
	SHLD	RT2+1
	RET			;AND GO HOME

RDTIME:				;READS COMPUPRO SYSTEM SUPPORT CLOCK
				;SUPPLY YOUR OWN ROUTINE
CLKCP	EQU	50H+10		;CLOCK COMMAND PORT
	LXI	H,DATESTR	;POINT TO DATE STRING
	LXI	D,DIGTAB 	;POINT TO DIGIT TABLE
	MVI	C,5		;READ TWO COUNTER
RTWO:	MVI	B,2		;READ ONE COUNTER
;
; READ A DIGIT FROM CLOCK CHIP
; ENTRY: DE => DIGIT TABLE DATA ENTRY
;        HL => STRING POSITION
; EXIT:  ASCII DIGIT LOADED IN STRING
;        DE & HL INCREMENTED
;
RONE	LDAX	D		;GET DIGIT TABLE DATA
	INX	D		;BUMP TO NEXT ENTRY
	ADI	10H		;SET READ BIT
	OUT	CLKCP		;OUTPUT DIGIT DATA
	CPI	15H		;CHECK FOR HOURS 10 DIGIT
	IN	CLKCP+1		;READ BCD DIGIT FROM CLOCK
	JNZ	NOHOUR
	SUI	8
NOHOUR:	ADI	'0'		;MAKE ASCII
	MOV	M,A
	INX	H		;POINT TO NEXT STR POSITION
	DCR	B	
	JNZ	RONE		;GET SECOND DIGIT
	INX	H		;BUMP OVER SEPERATOR
	MOV	A,C
	CPI	3
	JNZ	NOBUMP
	INX	H		;BUMP OVER WHITE SPACE
NOBUMP:	DCR	C
	JNZ	RTWO		;READ TWO MORE DIGITS
	JMP	GOTOIT		;GO TO IT

DIGTAB:	DB	10,9,8,7,12,11,5,4,3,2 ;CLOCK DIGIT TABLE

GOTOIT:	LXI	H,DATESTR	;HL POINTS TO DATE STRING
	LXI	D,BEGDATE	;DE POINTS TO DATA AREA
	MVI	C,LENDAT	;MOVE 18 BYTES
MOVEIT:	MOV	A,M
	STAX	D
	INX	H
	INX	D
	DCR	C
	JNZ	MOVEIT
	
	LXI	D,UDMSG		;TELL WHAT WE HAVE DONW
	MVI	C,9
	CALL	BDOS
	RET

COMPAR:	LDAX	D	;RETURNS ZERO SET IF SAME
	ANI	5FH	;MAKE UPPER CASE
	CMP	M
	RNZ
	DCR	C
	RZ
	INX	H
	INX	D
	JMP	COMPAR

DATESTR:DB	'MM/DD/YY  HH:MM' 

FIRST:	DB	0

UDMSG:	DB	'Up Dated',CR,LF,'$'

VMES:	DB	'DATE'
VMLEN:	EQU	$-VMES
	ENDIF	;CLOCK

BEGBUFF: EQU	$
VERTXT:	 EQU	BEGBUFF+1+2
BEGDATE: EQU	VERTXT+VMLEN+1

	IF	WYSE200		
;
LABELS:		;THIS CODE IS USED ONCE AND THEN OVER-WRITTEN
;
       	LXI	H,WTABLE	;HL=> KEYS DATA TABLE
	MOV	E,M		;LSB
	INX	H		;MSB
	MOV	D,M		;DE=>1ST STRING TO SEND
	MVI	C,9
	PUSH	H
	CALL	BDOS		;FIRST STRING
DOKEYS:	POP	H
	INX	H 		;BUMP TO NEXT TABLE ENTRY
	MOV	A,M		;IS TABLE ENTRY=0?
	MOV	E,M		;LSB
	INX	H
	MOV	D,M		;MSB
	ORA	D		;IS ENTRY = 0
	JZ	DONE		;0=END OF TABLE
	PUSH	H		;SAVE OFFSET INTO TABLE
	MVI	C,9		;GET TABLE ENTRY,DE=>DATA STRING
	CALL	BDOS		;SEND IT
	JMP	DOKEYS

DONE:	LXI	H,0269H		;PUT BACK NORMAL JUMP
	SHLD	0101H		;AT 100H
	JMP	0269H		;WM NORMAL ENTRY POINT
;
WTABLE	DW	DTABLE		;POINT TO DATA TABLE
	DW	L0
	DW	U0
	DW	S0
	DW	L1
	DW	U1
	DW	S1
	DW	L2
	DW	U2
	DW	S2
	DW	L3
	DW	U3
	DW	S3
	DW	L4
	DW	U4
	DW	S4
	DW	L5
	DW	U5
	DW	S5
	DW	L6
	DW	U6
	DW	S6
	DW	L7
	DW	U7
	DW	S7
	DW	0		;END OF TABLE

	;DATA TO PROGRAM THE WYSE-200 FUNCTION KEYS
DTABLE	DB	ESC,'A','1','t'	;DIM AND REVERSE LABEL FIELDS
	DB	CR,'$'

L0	DB	esc,'z','0'			;label # 0
	DB	'Save Fil',cr,'$'
U0	DB	esc,'z','@',esc,'   H',cr,del,'$'
S0	DB	esc,'z','H',' ',cr,del,'$'

L1	DB	esc,'z','1'			;label # 1
	DB	'End Edit',cr,'$'
U1	DB	esc,'z','A',esc,'   E',cr,del,'$'
S1	DB	esc,'z','I',' ',cr,del,'$'

L2	DB	esc,'z','2'	 		;label # 2
	DB	'Re-Start',cr,'$'
U2	DB	esc,'z','B',esc,'   O',cr,del,'$'
S2	DB	esc,'z','J',' ',cr,del,'$'

L3	DB	esc,'z','3'			;label # 3
	DB	' QUIT  >',cr,'$'
U3	DB	esc,'z','C',esc,'   Q',cr,del,'$'
S3	DB	esc,'z','K',' ',cr,del,'$'

L4	DB	esc,'z','4'			;label # 4
	DB	'<  Find ',cr,'$'
U4	DB	esc,'z','D',esc,'  <n',del,'$'
S4	DB	esc,'z','L',' ',cr,del,'$'

L5	DB	esc,'z','5'			;label # 5
	DB	' Replace',cr,'$'
U5	DB	esc,'z','E',esc,'  <r',del,'$'
S5	DB	esc,'z','M',' ',cr,del,'$'

L6	DB	esc,'z','6'			;label # 6
	DB	'Begining',cr,'$'
U6	DB	esc,'z','F',esc,'   B',cr,'   V',cr,del,'$'
S6	DB	esc,'z','N','  ',cr,del,'$'

L7	DB	esc,'z','7'			;label # 7
	DB	' Ending ',cr,'$'
U7	DB	esc,'z','G',esc,'   -B',cr,'   V',cr,del,'$'
S7	DB	esc,'z','O',' ',cr,del,'$'
	ENDIF	;WYSE200

	END



