home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ZSYS
/
SIMTEL20
/
ZSIG
/
WSZ3PAT.ASM
< prev
next >
Wrap
Assembly Source File
|
2000-06-30
|
11KB
|
468 lines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; WSPATCH.ASM ;
; ;
; Patch for Wordstar 3.0 running under ;
; The Echelon 'Z' System. Modifies ;
; Wordstar to use the current terminal ;
; characteristics defined in Z3TCAP. ;
; ;
; Copyright (c) 1985 by Dennis Wright ;
; and Echelon, Inc. ;
; ;
; Contains selected routines from ;
; ZCPR3's VLIB. ;
; ;
; VLIB is Copyrighted by Richard Conn ;
; and Echelon Inc. ;
; ;
; Note: It may be possable to install ;
; this patch on other versions of Word- ;
; Star if the equates below are changed ;
; to agree with versions' addresses. ;
; ;
; WordStar is a trademark of ;
; MicroPro International Corporation ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
MACLIB Z3BASE
;
; WordStar 3.0 USER1 Patch Addresses from Installation manual.
;
TNAME EQU 0190H ; Terminal name (not documented in manual).
HITE EQU 0248H ; Number of lines.
WID EQU 0249H ; Number of columns.
ERAEOL EQU 026DH ; Erase to end of line.
LINDEL EQU 0274H ; Delete line.
LININS EQU 027BH ; Insert line.
IVON EQU 0284H ; Highlighting on.
IVOFF EQU 028BH ; Highlighting off.
DELMIS EQU 02AFH ; Delay for non-cursor set functions.
TRMINI EQU 0292H ; Terminal init string.
TRMUNI EQU 029BH ; Terminal de-init string.
UCRPOS EQU 0264H ; User cursor positioning routine.
INISUB EQU 02A4H ; User init routine.
MORPAT EQU 02E0H ; WordStar user patch area.
PBGMEM EQU 035CH ; Contains beginning of text buffer address.
OCHAR EQU 0267H ; Contains address of WordStar outchr routine.
;
; The following equate is the base address of the patch routines.
;
PATCH EQU 7849H ; Get this address from original PBGMEM.
;
ORG UCRPOS ; User-patchable cursor positioning routine.
JMP XYPOS ; Use VLIB cursor positioning routine.
;
ORG INISUB ; User-patchable init subroutine.
JMP INIT ; Use patch init routine.
;
ORG MORPAT ; WordStar user patch area.
INIT: LXI H,Z3ENV ; Point to 'Z' System environment descriptors.
LXI D,80H
SHLD ENVPTR ; Save pointer.
PUSH H ; Save for later.
DAD D ; Displace to Z3TCAP.
SHLD VIDPTR ; Save pointer.
LHLD OCHAR ; Address of WS outchr routine is kept here.
SHLD COUT1+1 ; Inline modify patch cout to use WS outchr.
POP H ; Restore env pointer.
LXI D,47 ; Offset to Z3TCAP crt select byte.
DAD D
MOV A,M ; Get it.
LXI D,2 ; Set offset to crt 0 data area.
ORA A ; Crt 0?
JZ GETCRT ; Yes move crt 0 data to WS patch area.
LXI D,5 ; No, move crt 1 data.
GETCRT: DAD D ; Offset to selected Z3TCAP crt data area.
MOV A,M ; Get Z3TCAPs terminal width.
STA WID ; Patch WS width.
INX H ; Bump to Z3TCAPs number of lines.
MOV A,M ; Get number of lines.
STA HITE ; Patch WS hite.
XRA A ; Clear following WS patchs.
STA LINDEL ; Line delete
STA LININS ; ..and line insert (we don't support these).
LHLD VIDPTR ; Get Z3TCAP pointer.
LXI D,22 ; Offset to CE delay.
DAD D
MOV A,M ; Get CE delay.
STA DELMIS ; Patch WS misc delay.
INX H
CALL VIDSKP ; Skip past CL string.
CALL VIDSKP ; Skip past CM string.
LXI D,ERAEOL ; Point to WS eol string.
CALL FILL ; Replace with Z3TCAPs eol string.
LXI D,IVON ; Point to WS turn on highlighting.
CALL FILL ; Replace with Z3TCAPs string.
LXI D,IVOFF ; Point to WS turn off highlighting.
CALL FILL ; Replace with Z3TCAPs string.
LXI D,TRMINI ; Point to WS terminal init string.
CALL FILL ; Replace with Z3TCAPs string.
LXI D,TRMUNI ; Point to WS terminal de-init string.
CALL FILL ; Replace with Z3TCAPs string.
CALL NAMIT ; Replace WS terminal name with Z3TCAPs.
RET ; We're done.
;
ORG PBGMEM ; The beginning of the text memory is
DW BEGMEM ; ..moved up to accommidate our patch.
;
ORG PATCH ; Extended patch area.
NAMIT: LHLD VIDPTR ; Point to Z3TCAPs terminal name
LXI D,TNAME ; ..and WS terminal name.
MVI C,16 ; Move our 16 bytes.
NFILL: MOV A,M
STAX D
INX H
INX D
DCR C
JNZ NFILL
XCHG
NFILL2: MOV A,M ; Pad out the remainder with spaces.
CPI 0FH ; Till this.
RZ
ORA A ; Or zero.
RZ
MVI A,20H
MOV M,A
INX H
JMP NFILL2
;
; This routine moves Z3TCAP data into the WordStar patch area.
; Because WordStar requires the number of bytes for each entry
; we must count the bytes we patch and place the number at the
; beginning of the patch.
;
FILL: PUSH D
MVI C,-1 ; Set byte counter.
FIL1: INX D
MOV A,M ; Replace WS data with Z3TCAPs.
STAX D
INX H
INR C
ORA A ; Reached end?
JNZ FIL1
POP D ; Yes, restore pointer to first byte.
MOV A,C ; Insert number of bytes in string.
STAX D
RET
;
COUT: PUSH H
PUSH D
COUT1: CALL 0000H ; This is inline modified by the INIT.
POP D ; Routine to call WordStars outchr
POP H ; ..routine.
RET
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; The following routines are from VLIB by Richard Conn.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; GOTO XY (From VLIB)
; HL = Row/Col, with Home=0/0
; Return with A=0 and Zero Flag Set if not done
;
XYPOS: MOV D,L ; Swap row & column
MOV E,H ; ..for vlib
XCHG
GOTOXY: PUSH B ; Save regs
PUSH D
PUSH H
LHLD VIDPTR ; Pt to environment
MOV A,M ; No terminal?
CPI ' '+1
JC ERR
LXI D,15H ; Pt to CM delay
DAD D
MOV A,M ; Get it
STA CMDELAY ; Save it
INX H ; Pt to CL string
INX H
CALL VIDSKP ; Skip CL string
MOV A,M ; Get first char of CM string
ORA A ; If no string, error
JZ ERR
XCHG ; DE=address of CM string
POP H ; Get coordinates in HL
PUSH H
CALL GXY ; Output xy string with delay
LDA CMDELAY ; Pause
CALL VIDELAY
POP H ; Done
POP D
POP B
XRA A ; Return NZ
DCR A
RET
ERR: POP H ; Done
POP D
POP B
XRA A ; Return Z
RET
;
; GOTOXY (From VLIB)
; On input, H=Row and L=Column to Position To (0,0 is Home)
; On input, DE=address of CM string
;
GXY: XRA A ; Set row/column
STA RCORDER ; Row before column
STA RCBASE ; Add 0 to base
;
; Cycle thru string
;
GXYLOOP:LDAX D ; Get next char
INX D ; Pt to next
ORA A ; Done?
RZ
CPI '%' ; Command?
JZ GXYCMD
CPI '\' ; Escape?
JZ GXYESC
CALL COUT ; Send char
JMP GXYLOOP
;
; Escape - output following byte literally
;
GXYESC: LDAX D ; Get next char
CALL COUT ; Output literally
INX D ; Pt to next
JMP GXYLOOP
;
; Interpret next character as a command character
;
GXYCMD: LDAX D ; Get command char
INX D ; Pt to next
CPI 'd' ; %d
JZ GXYOUT1
CPI '2' ; %2
JZ GXYOUT2
CPI '3' ; %3
JZ GXYOUT3
CPI '.' ; %.
JZ GXYOUT4
CPI '+' ; %+v
JZ GXYOUT5
CPI '>' ; %>xy
JZ GXYGT
CPI 'r' ; %r
JZ GXYREV
CPI 'i' ; %i
JZ GXYINC
CALL COUT ; Output char if nothing else
JMP GXYLOOP
;
; Set row/col home to 0,0
;
GXYINC: MVI A,1 ; Set rcbase to 1
STA RCBASE
JMP GXYLOOP
;
; Reverse order of output to column then row (default is row then column)
;
GXYREV: MVI A,1 ; Set column and row order
STA RCORDER
JMP GXYLOOP
;
; Command: >xy
; If value of row/col is greater than x, add y to it
;
GXYGT: CALL GETVAL ; Get value
MOV C,A ; Save value
LDAX D ; Get value to test
INX D ; Pt to next
CMP C ; If carry, value>x
JNC GXYGT1
LDAX D ; Get value to add
ADD C
CALL PUTVAL ; Put value back
GXYGT1: INX D ; Pt to next
JMP GXYLOOP ; Resume
;
; Command: +n
; Add n to next value and output
;
GXYOUT5:LDAX D ; Get value to add
INX D ; Pt to next
MOV B,A ; Save in B
CALL GETVAL ; Get value
ADD B ; Add in B
CALL COUT ; Output value
RCMARK: LDA RCORDER ; Mark output
ORI 80H
STA RCORDER
JMP GXYLOOP
;
; Command: .
; Output next value
;
GXYOUT4:CALL GETVAL ; Get value
CALL COUT ; Output value
JMP RCMARK
;
; Command: 3
; Output next value as 3 decimal digits
;
GXYOUT3:CALL GETVAL ; Get value
MVI B,100 ; Output 100's
MVI C,1 ; Leading zeroes
CALL DIGOUT
GXYOT3: MVI B,10 ; Output 10's
MVI C,1 ; Leading zeroes
GXYOT2: CALL DIGOUT
ADI '0' ; Output 1's
CALL COUT
JMP RCMARK
;
; Command: 2
; Output next value as 2 decimal digits
;
GXYOUT2:CALL GETVAL ; Get value
JMP GXYOT3
;
; Command: d
; Output next value as n decimal digits with no leading zeroes
;
GXYOUT1:CALL GETVAL ; Get value
MVI B,100 ; Output 100's
MVI C,0 ; No leading zeroes
CALL DIGOUT
MVI B,10 ; Output 10's
MVI C,0 ; No leading zeroes
JMP GXYOT2
;
; Return next value in A
;
GETVAL: LDA RCORDER ; Get order flag
ORA A ; Already output the first value?
JM GETVAL2
ANI 1 ; Look at lsb
JZ GETVALR ; If 0, row first
GETVALC:LDA RCBASE ; Get base offset
ADD L ; Get column
RET
;
GETVALR:LDA RCBASE ; Get base offset
ADD H ; Get row
RET
;
GETVAL2:ANI 1 ; Look at lsb
JZ GETVALC
JMP GETVALR
;
; Store A as next value
;
PUTVAL: MOV C,A ; Save value
LDA RCORDER ; Get order flag
ORA A ; Already output the first value?
JM PUTVAL2
ANI 1 ; Look at lsb
JZ PUTVALR ; If 0, row first
PUTVALC:MOV L,C ; Set column
RET
;
PUTVALR:MOV H,C ; Set row
RET
;
PUTVAL2:ANI 1 ; Look at lsb
JZ PUTVALC
JMP PUTVALR
;
; Output A as decimal digit char
; B=Quantity to Subtract from A, C=0 if no leading zero
;
DIGOUT: PUSH D ; Save DE
MVI D,'0' ; Char
DECOT1: SUB B ; Subtract
JC DECOT2
INR D ; Increment char
JMP DECOT1
;
DECOT2: ADD B ; Add back in
PUSH PSW ; Save result
MOV A,D ; Get digit
CPI '0' ; Zero?
JNZ DECOT3
MOV A,C ; Get zero flag
ORA A ; 0=no zero
JZ DECOT4
DECOT3: MOV A,D ; Get digit
CALL COUT ; Print it
DECOT4: POP PSW ; Get A
POP D ; Restore DE
RET
;
; GXY Buffers
;
RCORDER:DS 1 ; 0=row/col, else col/row
RCBASE: DS 1 ; 0=org is 0,0, else org is 1,1
CMDELAY:DS 1 ; Number of milliseconds to delay for CM
;
; VIDELAY pauses for the number of milliseconds indicated by the A
; register. VIDELAY assumes a ZCPR3 environment and uses it to determine
; processor speed.
;
VIDELAY:PUSH PSW ; Save regs
PUSH B
PUSH D
PUSH H
MOV C,A ; Save count in C
ORA A ; No delay?
JZ DONE
LHLD ENVPTR ; Pt to environment
LXI D,2BH ; Offset to processor speed
DAD D
MOV A,M ; Get processor speed
ORA A ; Zero?
JNZ VID1
MVI A,4 ; Assume 4 MHz
VID1: MOV B,A ; Processor speed in B
VID2: PUSH B ; Delay 1 ms
CALL DELAY
POP B
DCR C ; Count down
JNZ VID2
DONE: POP H ; Restore regs
POP D
POP B
POP PSW
RET
;
; Delay 1 ms at Clock speed
;
DELAY: CALL DEL1 ; Delay 1 ms at 1MHz
DCR B ; Count down clock speed
JNZ DELAY
RET
;
; Delay 1 ms at 1MHz
;
DEL1: MVI C,20 ; 20 loops of 51 cycles each ~ 1000 cycles
DEL1A: XTHL ; 18 cycles
XTHL ; +18 = 36 cycles
DCR C ; + 5 = 41 cycles
JNZ DEL1A ; +10 = 51 cycles
RET
;
; VIDSKP - Skip over video string pted to by HL; pt to byte after string
;
VIDSKP: MOV A,M ; Get next char
INX H ; Pt to next
ORA A ; Done if zero
RZ
CPI '\' ; Literal value?
JNZ VIDSKP ; Continue if not
INX H ; Pt to after literal value
JMP VIDSKP
;
; ZCPR3 Pointer save area
;
VIDPTR: DS 2 ; First byte of termcap entry
ENVPTR: DS 2 ; 'Z' System environment package.
;
BEGMEM EQU $
;
END