home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
msr313src.tar.gz
/
msr313src.tar
/
msggri.asm
< prev
next >
Wrap
Assembly Source File
|
1991-03-18
|
50KB
|
1,509 lines
Name msggri
; File MSGIBM.ASM
include mssdef.h
; Copyright (C) 1982,1991, Trustees of Columbia University in the
; City of New York. Permission is granted to any individual or
; institution to use, copy, or redistribute this software as long as
; it is not sold for profit and this copyright notice is retained.
; Tektronix emulator for use with MS Kermit/IBM.
; Edit history:
; 2 March 1991 version 3.10
; John Nyenhuis Purdue University School of Electrical Engineering
; West Lafayette IN 47907 (317)494-3524 nyenhuis@ee.ecn.purdue.edu
; November 1988
; Modify msgibm.asm to work with the GRiD Compass II
; Functionality is same as for IBM except for the more message in OUTSCRN
;
; Last edit 22 May 1988
; 1 July 1988 Version 2.31
; 22 May 1988 Add support for ESC [ Pn ; Pn m (ANSI) screen coloring.
; 22 March 1988 Add global byte Tekgraf which forces graphics board type
; 0=auto-sensing, 1=cga, 2=ega, 3=VGA, 4=Hercules, 5=ATT. Tekgraf stored
; here and set in file MSX by Set Term Graphics <board type>. Permit chars
; to overlap existing pixels. [jrd]
; 27 Feb 1988 Add tests for Toshiba T3100 (tnx for assist from Rob Preuss),
; for Olivetti M28/AT&T 6300+, and for DEC VAXmate II (tnx to Frank da Cruz)
; Add pointer based dispatch to character-font drawing routine. Add tests
; for stdin being a file rather than a device (keyboard). [jrd]
; 27 Jan 1988 Supress GIN and Status echos with Bypass byte. Bypass is reset
; by receipt of BEL, LF, CR, US, escape sequences, terminal reset.
; Bypass is set by receipt of ESC Control-E, ESC Control-X, ESC Control-Z.
; Make GIN mode crosshairs remember last GIN mode postion until the terminal
; is reset; make major steps smaller. Add ESC query-mark stands for DEL.
; Make Horizontal Tab (Control-I) a non-printing cursor control character
; to move right one column (with line wrap). Let real Hercules boards use
; both pages of memory (clones behave differently), tnx to Daniel Gruner.
; 1 Jan 1988 version 2.30
; 31 Dec 1987 change name from msvibm to msgibm for final release. [jrd]
; 29 Dec 1987 Add ESC [ ? 3 8 l as exit Tek mode command, from VT340's.[jrd]
; 26 Dec 1987 Add test to absorb echo of crosshairs report. [jrd]
; 22 Dec 1987 Revise parsing rules to make an escape sequence be a temporary
; interruption to the current command (except Clear Screen seq). [jrd]
; Add Control-C and Control-Break as non-reporting exits from GIN mode. [jrd]
; 21 Dec 1987 Add AT&T 6300, Olivetti M24 presence tests and run code. [jrd]
; 16 Dec 1987 Correct screen coloring for 64KB mono/med res color egas. [jrd]
; 4 Dec 1987 Add quirks for Environments, such as TopView, Windows. [jrd]
; 3 Dec 1987 Let 128KB EGA boards save screens. [jrd]
; 30 Nov 1987 Add relative plotting, thanks to help from Bob Parks. [jrd]
; 24 Nov 1987 Add dashed line patterns. [jrd]
; 21 Nov 1987 Add full color background. [jrd]
; 15 Nov 1987 Do screen clears manually because a Bios mode-set keeps
; interrupts off long enough to miss serial port characters. Make crosshairs
; smaller. [jrd]
; 8 Nov 1987 Modularize line drawing using Bresneham's algorithm, use pointers
; to action routines for different board types. Add screen save/restore.
; Do display board presence tests. Add FS as point plot introducer. Allow
; for virtual screens when operating under Environments (Windows, etc). [jrd]
; 1 Nov 1987 Heavy rewrite to integrate code into regular MS Kermit/IBM
; material. [jrd]
;==============================================================================
; Original version for TI Pro computers by
; 12-Dec-84 Joe Smith, CSM Computing Center, Golden CO 80401
; adapted to IBM PC June 1987 by Brian Holley,
; Faculty of Economics and Politics
; University of Cambridge, England
; Email: BJH6@UK.AC.CAM.PHX
; Upgraded and integrated into MS Kermit 2.30 by Joe Doupnik, Utah State Univ.
;
; Description of Tektronix commands
;
; ESCAPE-CONTROL-E (ENQ) requests a status report
; ESCAPE-FORMFEED erases the screen.
; ESCAPE-CONTROL-X turns on bypass mode (no screen characters).
; ESCAPE-CONTROL-Z turns on the crosshairs (not on 4006 or 4025)
; ESCAPE-? is replaced by DEL code, to assist line plots with 7 bit systems.
; ESCAPE [ Pn ; Pn m set screen colors. Pn = 30 + sum of colors for foregnd,
; 40 + sum of colors for background, Pn = 0 sets b/w, Pn = 1 for high
; intensity. Colors are red = 1, green = 2, blue = 4.
; ESCAPE [ ? 3 8 l exits Tek mode and returns to host text terminal type
; (VT102 if none defined yet). This is an extension from DEC VT340's.
; CONTROL-] (GS) turns on plot mode, the first move will be with beam off.
; CONTROL-^ (RS) turns on incremental plot mode. RS space means move pen up
; RS P means move pen down, following letters:A, E, D, F, B, J, H, I mean
; move right, right and up, up, left and up, left, left and down, down, and
; right and down, respectively. Ex: RS <space> J J J means move three Tek
; positions left and down with the pen up (invisibly).
; CONTROL-UNDERLINE (US) turns off plot mode, as does CR (for all but 4025).
; CONTROL-X switches from TEKTRONIX sub mode to NORMAL alpha mode but is
; ignored if we are emulating a full Tek terminal rather than a sub mode
; of DEC or Heath.
; FF erases screen.
; ESCAPE letter, where letter is accent grave (`), a-e sets the line drawing
; pattern until reset to solid lines (same as escape accent) by command or
; a terminal reset.
; where
; ENQ = Control E
; ESC = Control [ (left square bracket)
; FF = Control L
; FS = Control \ (backslash)
; GS = Control ] (right square bracket)
; RS = Control ^ (caret)
; US = Control _ (underscore)
;
; The plot commands are characters which specify the absolute position to move
; the beam. All moves except the one immediately after the GS character
; (Control-]) are with a visible trace.
;
; For 4010-like devices - The positions are from 0 to 1023 for both X and Y,
; although only 0 to 780 are visible for Y due to screen geometry. The screen
; is 10.23 by 7.80 inches, and coordinates are sent as 1 to 4 characters.
;
; For 4014-like devices - The positions are from 0 to 4096, but each movement
; is a multiple of 4 positions unless the high-resolution LSBXY are sent. This
; makes it compatible with the 4010 in that a full sized plot fills the screen.
;
; HIX,HIY = High-order 5 bits of position
; LOX,LOY = Middle-order 5 bits of position
; LSBXY = Low-order 2 bits of X + low-order 2 bits of Y (4014 mode)
;
; Hi Y Lo Y Hi X LSBXY Characters sent (Lo-X always sent)
; ---- ---- ---- ----- ----------------------------------
; Same Same Same Same Lo-X
; Same Same Same Diff LSB, Lo-Y, Lo-X 4014
; Same Same Diff Same Lo-Y, Hi-X, Lo-X
; Same Same Diff Diff LSB, Lo-Y, Hi-X, Lo-X 4014
; Same Diff Same Same Lo-Y, Lo-X
; Same Diff Same Diff LSB, Lo-Y, Lo-X 4014
; Same Diff Diff Same Lo-Y, Hi-X, Lo-X
; Same Diff Diff Diff LSB, Lo-Y, Hi-X, Lo-X 4014
; Diff Same Same Same Hi-Y, Lo-X
; Diff Same Same Diff Hi-Y, LSB, Lo-Y, Lo-X 4014
; Diff Same Diff Same Hi-Y, Lo-Y, Hi-X, Lo-X
; Diff Same Diff Diff Hi-Y, LSB, Lo-Y, Hi-X, Lo-X 4014
; Diff Diff Same Same Hi-Y, Lo-Y, Lo-X
; Diff Diff Same Diff Hi-Y, LSB, Lo-Y, Lo-X 4014
; Diff Diff Diff Same Hi-y, Lo-Y, Hi-X, Lo-X
; Diff Diff Diff Diff Hi-y, LSB, Lo-Y, Hi-X, Lo-X 4014
; Offset for byte: 20h 60h 60h 20h 40h
;
; Note that LO-Y must be sent if HI-X has changed so that the TEKTRONIX knows
; the HI-X byte (in the range of 20h-3fh) is HI-X and not HI-Y. LO-Y must
; also be sent if LSBXY has changed, so that the 4010 will ignore LSBXY and
; accept LO-Y. The LSBXY byte is 60h + MARGIN*10h + LSBY*4 + LSBX. (MARGIN=0)
;
;
;
; External variable tekflg and calls to tekini, tekemu, tekesc, tekcls:
; Byte TEKFLG is non-zero when the Tek emulator is active; it is set by the
; startup code in tekini and is maintained in this file. Internal variable
; inited remembers if we have a graphics screen saved, etc.
; TEKINI must be called when entering the emulator to establish the graphics
; screen mode and to calculate the screen dimensions.
; TEKRINT reinitialize complete emulator.
; TEKESC is called from say mszibm.asm to invoke Tek emulation when the
; external procedures have detected an Escape Control-L sequence. An implicit
; initialization is done if necessary.
; TEKEMU is the normal entry point to pass a received character to the emulator.
; It too will do an implicit initialization, if required.
; TEKCLS clears the graphics screen, but only if the emulator is active.
; The emulator remains active during Connect mode Help, Status, and other
; interrupts which do not change the terminal type.
public tekemu,tekini,tekrint,tekend,tekgraf ; Terminal emulation
public tekcls, tekesc, tekflg ; used by msz file
ENQ equ 05h ; ^E ENQ for TEK enquiries
CAN equ 18h ; ^X to return to ANSI mode
ESCZ equ 1Ah ; SUB, ESC-^Z triggers crosshairs
VT equ 0bh ; ^K go up one line
FS equ 1ch ; ^\ for point plot mode
GS equ 1Dh ; ^] draw line (1st move is invisible)
RS equ 1Eh ; ^^ for incremental line plot mode
US equ 1Fh ; ^_ (underscore) returns to text mode
accent equ 60h ; accent grave
txtmode equ 4 ; text mode for TEKTRONIX status
maxtekx equ 1024 ; horizontal and
maxteky equ 780 ; vertical resolution of TEK 4010
uparr equ 72 ; DOS scan codes for arrow keys
dnarr equ 80
lftarr equ 75
rgtarr equ 77
homscn equ 71 ; DOS home screen scan code
shuparr equ 73 ;code-arrow keys [jan]
shdnarr equ 81
shlftarr equ 212
shrgtarr equ 213
segcga equ 0040h ; grid display start [jan]
hiy equ 1 ; codes for Tek graphics components
loy equ 2
hix equ 4
lox equ 3
data segment public 'data'
extrn flags:byte, portval:word, rxtable:byte
extrn bigscreen:byte, denyflg:word ; control tek auto entry/exit
xmult dw 5 ; 320 = (5/16)*1024 small scrn [jan]
xdiv dw 16 ; xmult/xdiv
ymult dw 12 ; 240=(12/39)*780 small scrn [jan]
ydiv dw 39 ; ymult/ydiv
xmax dw 312 ; 320-8 x coord of right most chr [jan]
ybot dw 239 ; 240 lines on small scrn [jan]
linelen dw 40 ; offset increment between scan lines
linebytes dw 40 ;40 bytes/line on small scn [jan]
ttstate dw tektxt ; state machine control pointer
prestate dw 0 ; previous state, across interruptions
visible db 0 ; 0 to move, 1 to draw a line
tek_hiy dw 0 ; Y coordinate in Tektronix mode
tek_loy db 0
tek_hix dw 0 ; X coordinate in Tektronix mode
tek_lox db 0
tek_lsb db 0 ; Low-order 2 bits of X + low Y
; (4014 mode)
status db 0
lastc db 0 ; last x/y coord fragment seen
masktab db 80h,40h,20h,10h,8,4,2,1 ; quicker than calculations!
; dashed line patterns
linetab dw 0ffffh ; ESC accent 11111111 11111111
dw 0aaaah ; ESC a 10101010 10101010
dw 0f0f0h ; ESC b 11110000 11110000
dw 0fafah ; ESC c 11111010 11111010
dw 0ffcch ; ESC d 11111111 11001100
dw 0fc92h ; ESC e 11111100 10010010
linepat dw 0ffffh ; active line pattern, from above
;End of init data
IDSEQ dw tekem ; address of response to terminal
CTLTAB dw 0 ; .. inquiry
tekem db 'GRiD_TEK' ; .. and the response
db escape,'/Z',0
x_coord dw 0 ; Tek text char X coordinate
y_coord dw 8 ; Tek text char Y coordinate
xcross dw 0 ; cross hairs to start at centre
ycross dw 0
oldx dw 0 ; Tek coordinates of last point
oldy dw 767 ; initially top left
scalex dw 0 ; PC coord for scaled x value
scaley dw 0 ; for scaled y value
curmode db 0 ; screen mode before graphics
tekgraf db 1 ; Tek graphics board selection (def=cga)[jan]
; local variables for LINE plotting routine
cursor dw 0 ; saved text cursor
inited db 0 ; non-zero if inited (retains page)
tekflg db 0 ; Tek mode active flag
yflags db 0 ; flags byte from msy
flow dw 0 ; flow control word
gpage db 0 ; display adapter graphics page
gfcol db 15 ; graphics foreground colour
gbcol db 0 ; graphics background color
tfcol db 0 ; temp foreground color
tbcol db 0 ; temp background color
lastd db 0,0 ; worker for ESC [ Pn ; Pn m scanner
ccode db 0 ;coloring
moremsg db ' More >'
mormsglen equ $-moremsg ; length of message
putc dw gputc ; ptr to plot a character routine
psetup dw psetupc ; ptr to plot setup routine
pincy dw pincyc ; ptr to inc y routine
plotptr dw pltcga ; ptr to dot plot routine
gcplot dw gcgen ; ptr to char plot routine
segscn dw 0040h ; actual screen segment to use[jan]
; ANSI Escape sequence to exit Tek mode
tkoff db escape,'[?38l' ; Exit Tek mode escape sequence
tkofflen equ $-tkoff ; length of sequence
tkoffs db 6 dup (0) ; received chars in rcv'd sequence
tkcnt dw 0 ; counter of matched char in tkoffs
bypass db 0 ; GIN mode bypass condition (0=off)
temp dw 0
; 8*8 font for Hercules and such, CGA, and EGA
; - allows 43 lines, and 80 (90 for Hercules) chars per line.
; all printing (?) characters from <space> to <del> - two characters per line
; 8 bits per scan line, given top line first, 8 scan lines.
font db 0,0,0,0,0,0,0,0, 18h,18h,18h,18h,18h,0,18h,0
db 6ch,6ch,6ch,0,0,0,0,0, 36h,36h,7fh,36h,7fh,36h,36h,0
db 0ch,3fh,68h,3eh,0bh,7eh,18h,0, 60h,66h,0ch,18h,30h,66h,06h,0
db 38h,6ch,6ch,38h,6dh,66h,3bh,0, 0ch,18h,30h,0,0,0,0,0
db 0ch,18h,30h,30h,30h,18h,0ch,0, 30h,18h,0ch,0ch,0ch,18h,30h,0
db 0,18h,7eh,3ch,7eh,18h,0,0, 0,18h,18h,7eh,18h,18h,0,0
db 0,0,0,0,0,18h,18h,30h, 0,0,0,7eh,0,0,0,0
db 0,0,0,0,0,18h,18h,0, 0,06h,0ch,18h,30h,60h,0,0
db 3ch,66h,6eh,7eh,76h,66h,3ch,0, 18h,38h,18h,18h,18h,18h,7eh,0
db 3ch,66h,06h,0ch,18h,30h,7eh,0, 3ch,66h,06h,1ch,06h,66h,3ch,0
db 0ch,1ch,3ch,6ch,7eh,0ch,0ch,0, 7eh,60h,7ch,06h,06h,66h,3ch,0
db 1ch,30h,60h,7ch,66h,66h,3ch,0, 7eh,06h,0ch,18h,30h,30h,30h,0
db 3ch,66h,66h,3ch,66h,66h,3ch,0, 3ch,66h,66h,3eh,06h,0ch,38h,0
db 0,0,18h,18h,0,18h,18h,0, 0,0,18h,18h,0,18h,18h,30h
db 0ch,18h,30h,60h,30h,18h,0ch, 0,0,0,7eh,0,7eh,0,0,0
db 30h,18h,0ch,06h,0ch,18h,30h, 0,3ch,66h,0ch,18h,18h,0,18h,0
db 3ch,66h,6eh,6ah,6eh,60h,3ch, 0,3ch,66h,66h,7eh,66h,66h,66h,0
db 7ch,66h,66h,7ch,66h,66h,7ch, 0,3ch,66h,60h,60h,60h,66h,3ch,0
db 78h,6ch,66h,66h,66h,6ch,78h, 0,7eh,60h,60h,7ch,60h,60h,7eh,0
db 7eh,60h,60h,7ch,60h,60h,60h, 0,3ch,66h,60h,6eh,66h,66h,3ch,0
db 66h,66h,66h,7eh,66h,66h,66h, 0,7eh,18h,18h,18h,18h,18h,7eh,0
db 3eh,0ch,0ch,0ch,0ch,6ch,38h, 0,66h,6ch,78h,70h,78h,6ch,66h,0
db 60h,60h,60h,60h,60h,60h,7eh, 0,63h,77h,7fh,6bh,6bh,63h,63h,0
db 66h,66h,76h,7eh,6eh,66h,66h, 0,3ch,66h,66h,66h,66h,66h,3ch,0
db 7ch,66h,66h,7ch,60h,60h,60h, 0,3ch,66h,66h,66h,6ah,6ch,36h,0
db 7ch,66h,66h,7ch,6ch,66h,66h, 0,3ch,66h,60h,3ch,06h,66h,3ch,0
db 7eh,18h,18h,18h,18h,18h,18h, 0,66h,66h,66h,66h,66h,66h,3ch,0
db 66h,66h,66h,66h,66h,3ch,18h, 0,63h,63h,6bh,6bh,7fh,77h,63h,0
db 66h,66h,3ch,18h,3ch,66h,66h, 0,66h,66h,66h,3ch,18h,18h,18h,0
db 7eh,06h,0ch,18h,30h,60h,7eh, 0,7ch,60h,60h,60h,60h,60h,7ch,0
db 0,60h,30h,18h,0ch,06h,0,0, 3eh,06h,06h,06h,06h,06h,3eh,0
db 18h,3ch,66h,42h,0,0,0,0, 0,0,0,0,0,0,0,0ffh
db 30h,18h,0ch,0,0,0,0,0, 0,0,3ch,06h,3eh,66h,3eh,0
db 60h,60h,7ch,66h,66h,66h,7ch,0, 0,0,3ch,66h,60h,66h,3ch,0
db 06h,06h,3eh,66h,66h,66h,3eh,0, 0,0,3ch,66h,7eh,60h,3ch,0
db 0eh,18h,18h,3ch,18h,18h,18h,0, 0,0,3eh,66h,66h,3eh,06h,3ch
db 60h,60h,7ch,66h,66h,66h,66h,0, 18h,0,38h,18h,18h,18h,3ch,0
db 18h,0,38h,18h,18h,18h,18h,70h, 60h,60h,66h,6ch,78h,6ch,66h,0
db 38h,18h,18h,18h,18h,18h,3ch,0, 0,0,76h,7fh,6bh,6bh,63h,0
db 0,0,7ch,66h,66h,66h,66h,0, 0,0,3ch,66h,66h,66h,3ch,0
db 0,0,7ch,66h,66h,7ch,60h,60h,0, 0,3eh,66h,66h,3eh,06h,07h
db 0,0,6ch,76h,60h,60h,60h,0, 0,0,3eh,60h,3ch,06h,7ch,0
db 30h,30h,7ch,30h,30h,30h,1ch,0, 0,0,66h,66h,66h,66h,3eh,0
db 0,0,66h,66h,66h,3ch,18h,0, 0,0,63h,6bh,6bh,7fh,36h,0
db 0,0,66h,3ch,18h,3ch,66h,0, 0,0,66h,66h,66h,3eh,06h,3ch
db 0,0,7eh,0ch,18h,30h,7eh,0, 0ch,18h,18h,70h,18h,18h,0ch,0
db 18h,18h,18h,0,18h,18h,18h,0, 30h,18h,18h,0eh,18h,18h,30h,0
db 31h,6bh,46h,0,0,0,0,0, 8 dup (0ffh)
data ends
code segment public 'code'
extrn outchr:near, beep:near, cmblnk:near
extrn clrmod:near, cptchr:near
extrn clrbuf:near, iseof:near, getflgs:near
extrn termtog:near ; toggle terminal type [jan]
assume cs:code, ds:data, es:nothing
; Initialise TEK mode by setting high resolution screen, etc
tekini PROC NEAR
push ax
push bx
push cx
push dx
push si
push di
push es
cmp bigscreen,0 ;1means big
je tekin1 ;eq means use defaults
mov xmult,1 ;512=(1/2) x 1024 big scrn [jan]
mov xdiv,2 ;512 columns on big screen
mov ymult,64 ;256=(64/195)*780
mov ydiv,195 ;256 rows on big screen
mov xmax,504 ;5-2-8 x coord of right most chr
mov ybot,255 ;256 lines on big screen
mov linelen,64 ;64 bytes per line
mov linebytes,64
jmp tekin2
tekin1: mov xmult,10 ;small screen stuff
mov xdiv,32 ;small is 320 x 240
mov ymult,12
mov ydiv,39
mov xmax,312
mov ybot,239
mov linelen,40
mov linebytes,40
tekin2: mov tekflg,1 ; starting Tek sub mode
; cmp inited,0 ; inited yet?
; jne tekin19 ; ne = yes, restore screen
mov ttstate,offset tektxt ; do displayable text
mov prestate,offset tektxt ; set a previous state of text
mov inited,1 ; say we have initialized
; call tekcls ; clear screen
; jmp short tekin20
;tekin19:call tekrest ; restore old graphics screen
tekin21:clc ; clear carry for success
tekin23:pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
tekini ENDP
TEKRINT proc near ; Tek reinitialization entry point
mov inited,0 ; do complete reinitialization
jmp tekini
TEKRINT endp
;Terminal emulation. Enter with received character in AL.
TEKEMU PROC NEAR ; main emulator
cmp tekflg,0 ; Tek mode active yet? (msz call)
jne tektt1 ; ne = yes
call tekini ; init now
mov ttstate,offset tektxt ; initial state
mov prestate,offset tektxt ; set a previous state of text
jnc tektt1 ; nc = succeeded
ret ; else failed to init, just return
tektt1: and al,7fh ; force Tek chars to be 7 bits
cmp al,0 ; NUL char?
je tekign ; e = yes, ignore it before logging
push ax
call getflgs ; get msy yflags into al
mov yflags,al
test al,capt ; capturing output?
pop ax
jz tektt4 ; z = no, forget this part
push ax ; save char
call cptchr ; give it captured character
pop ax ; restore character and keep going
tektt4: test yflags,trnctl ; debug? if so use tty mode
jz tektt5 ; z = no
cmp al,DEL ; DEL char?
jne tektt4a ; ne = no
mov al,5eh ; make DEL a caret query mark
call outscrn
mov al,3fh ; the query mark
call outscrn
jmp short tekign
tektt4a:cmp al,' ' ; control char?
jae tektt4b ; ne = no
push ax
mov al,5eh ; caret
call outscrn
pop ax
add al,'A'-1 ; make char printable
tektt4b:call outscrn
tekign: ret ; Ignore this character
tektt5: call tkscan ; scan for "ESC [ ? 3 8 l" exit code
tektt5a:cmp al,0 ; null char response?
je tekign ; e = yes, ignore the character
cmp al,' ' ; control code?
jb tektt6 ; b = yes, decode
jmp ttstate ; no, do current state
; Control characters:
tektt6: cmp al,GS ; Line plot command?
jne tektt7 ; ne = no
mov visible,0 ; Next move is invisible
and status,not txtmode ; set status report byte
mov ttstate,offset tekline ; expect coordinates next
jmp tektt12
tektt7: cmp al,RS ; Incremental dot command?
jne tektt8 ; ne = no
and status,not txtmode ; set status report
mov ttstate,offset tekrlin ; expect pen command next
jmp tektt12
tektt8: cmp al,FS ; Point plot command?
jne tektt9 ; ne = no
mov visible,0 ; next move is invisible
and status,not txtmode ; set status report byte
mov ttstate,offset tekpnt
jmp tektt12
tektt9: cmp al,US ; assert text mode? [bjh]
jne tektt10 ; ne = no
or status,txtmode ; set status report byte
mov ttstate,offset tektxt ; Go to TEKTXT next time
mov bypass,0 ; reset bypass condition
jmp tektt12
tektt10:cmp al,ESCAPE ; Escape?
jne tektt11 ; ne = no
or status,txtmode ; set status report byte
cmp ttstate,offset tekesc ; already in escape state?
je tektt14 ; e = yes, nest no further
push ttstate ; current state
pop prestate ; save here as previous state
mov ttstate,offset tekesc ; next state parses escapes
ret
tektt11:cmp al,CAN ; Control X? (exits Tek sub mode)
jne tektt13 ; ne = no, stay in current state
cmp ttstate,offset tekesc ; ESC Control-X?
je tektt13 ; yes, parse it in tekesc code
mov ttstate,offset tektxt ; back to text mode
; test flags.vtflg,tttek ; main Tek emulator?
test denyflg,tekxflg ;disable auto exit/entry [jan]
jnz tektt12 ; nz = yes, ignore the ^X
call tekend ; else exit sub mode
mov tekflg,0 ; clear Tek sub mode flag
tektt12:mov prestate,offset tektxt ; make previous state text
tektt14:ret
tektt13:jmp ttstate ; let someone else worry about this
TEKEMU ENDP
; End TEK emulation, recover previous screen
TEKEND PROC NEAR
cmp tekflg,0 ; Tek sub mode active?
jne teknd0 ; ne = yes
ret ; else return as is.
teknd0: call termtog ;toggle terminal
ret
TEKEND ENDP
; State machine active while Tek is active. Senses ESC [ ? 3 8 l to exit
; Tek mode and return to either non-sub mode terminal or to a VT102.
; Plays back unmatched escape sequences. Enter with character in al.
tkscan proc near
and al,7fh ; strip high bit
cmp al,byte ptr tkoff ; start of Tek Off sequence?
jne tkscn1 ; ne = no
call tkscn4 ; playback previously matched chars
mov tkcnt,1 ; count matched chars (one now)
mov tkoffs,al ; save full character, with high bit
mov al,0 ; our temporary response
jmp short tkscnx ; and exit
tkscn1: push bx ; check for char in Tek Off sequence
mov bx,tkcnt ; number of chars matched in Tek Off
mov tkoffs[bx],al ; save this char
cmp al,byte ptr tkoff[bx] ; match expected char in sequence?
pop bx
jne tkscn3 ; ne = no, play back partial match
inc tkcnt ; count new match
mov al,0 ; our temporary response
cmp tkcnt,tkofflen ; matched all char in sequence?
jne tkscnx ; ne = not yet, wait for more
mov tkcnt,0 ; clear counter
cmp flags.vtflg,tttek ;full terminal now?
jne tkscn2 ; ne = no, a submode
; call termtog ; toggle terminal type[jan]
tkscn2: mov al,CAN ; simulate arrival of Control-X
jmp short tkscnx ; all done
tkscn3: call tkscn4 ; playback previously matched chars
mov tkcnt,0 ; reset to no match and exit
tkscnx: ret ; common exit
; local worker procedure
tkscn4: push ax ; save break char (in al)
push cx ; playback partial sequence to screen
mov cx,tkcnt ; number of chars matched before break
jcxz tkscn4b ; z = none
push si
mov si,offset tkoffs ; string to be played back
tkscn4a:cld
lodsb ; get a char into al
push cx
push si ; save these around tektt5a work
call tektt5a ; use it
pop si
pop cx
loop tkscn4a ; do all that came in previously
pop si
tkscn4b:pop cx
pop ax ; recover break char
ret
tkscan endp
TEKTXT proc near ; Dispatch on text characters
cmp al,DEL ; RUBOUT?
jne tektx1 ; ne = no
mov al,bs ; make BS
jmp short tektx7
tektx1: cmp al,CR ; carriage return (^M)?
je tektx9 ; e = yes
tektx2: cmp al,LF ; line feed (^J)?
je tektx9 ; e = yes
tektx3: cmp al,FF ; form feed (^L)?
jne tektx4 ; ne = no
call tekcls ; clear the screen
jmp short tektx8
tektx4: cmp al,VT ; vertical tab (^K)?
je tektx7
cmp al,bell ; bell (^G)?
jne tektx5 ; ne = no
call beep
mov bypass,0 ; clear GIN mode bypass condition
jmp short tektx8
tektx5: cmp al,tab ; horizontal tab (^I)?
je tektx7 ; e = yes
tektx6: cmp al,BS ; backspace (^H)?
je tektx7 ; e = yes
cmp al,' ' ; control char?
jb tektx8 ; b = yes, ignore it
tektx7: cmp bypass,0 ; bypass mode off?
jne tektx8 ; ne = no, it's on so skip display
call OUTSCRN ;output character to screen
tektx8: ret
tektx9: mov bypass,0 ; clear GIN mode bypass condition
jmp short tektx7
TEKTXT endp
; Process escape sequences. Callable from msz terminal emulator.
; Enter with received character in AL. Escape sequences are generally
; treated as interruptions to the current plotting/text command. Screen
; clearing is the exception by causing a general emulator reset.
TEKESC PROC NEAR
mov bypass,0 ; clear GIN mode bypass condition
mov ttstate,offset tekesc ; in case get here from msz file
cmp tekflg,0 ; Tek mode active yet? (msz call)
jne tekesc1 ; ne = yes
call tekini ; init now
mov prestate,offset tektxt ; set a previous state of text
jnc tekesc1 ; nc = succeeded
ret ; else failed to init, just return
tekesc1:cmp al,'Z' ; ESC-Z Identify?
jne tekesc2 ; ne = no
; call SENDID ; Send terminal identification
jmp tekescx
tekesc2:cmp al,FF ; ESC-FF Clear screen?
jne tekesc3 ; ne = no
call tekcls ; Clear screen
mov prestate,offset tektxt ; make previous state text mode
jmp tekescx ; Return to text mode after ESC-FF
tekesc3:cmp al,ESCZ ; ESC-^Z Enter GIN mode?
jne tekesc4 ; ne = no
mov bypass,1
call CROSHAIR ; Activate the cross-hairs
jmp tekescx
tekesc3a:call beep ; tell the user we are unhappy
jmp tekescx ; and ignore the command
tekesc4:cmp al,ENQ ; ESC-^E Enquiry for cursor position?
jne tekesc5 ; ne = no
mov bypass,1 ; set bypass mode
call SENDSTAT ; send status
jmp tekescx
tekesc5:cmp al,CAN ; ESC Control-X?
jne tekesc6 ; ne = no
mov bypass,1 ; set bypass condition
jmp tekescx
tekesc6:cmp al,3fh ; query mark? (ESC ? means DEL)
jne tekesc7 ; ne = no
mov al,DEL ; replace with DEL code
jmp tekescx ; and process it as if received.
tekesc7:cmp al,accent ; accent grave, line pattern series?
jb tekesc8 ; b = no
cmp al,65h ; lowercase e?
ja tekescx ; a = beyond line pattern series
push bx
mov bl,al
sub bl,accent ; remove bias
and bl,7 ; eight patterns, roll over excess
mov bh,0
shl bx,1 ; make this a word index
mov bx,linetab[bx] ; get line pattern word
mov linepat,bx ; save in active word
pop bx ; return to previous mode
tekesc8:cmp al,5bh ; right square bracket?
jne tekescx ; ne = no
; jmp tekcol ; no color on GRiD [jan]
tekescx:push ax
mov ax,prestate ; get previous state
mov ttstate,ax ; restore it
or ax,ax ; test for none
pop ax
jz go2text ; z = none, use text mode
clc
ret ; resume previous state
go2text:mov ttstate,offset tektxt ; Go to TEKTXT next time
mov lastc,0 ; clear last drawing coordinate flag
or status,txtmode ; set text mode in status byte
clc
ret
TEKESC ENDP
TEKLINE proc near ; GS line drawing
call tekxyc ; parse coordinates from input bytes
jnc teklin1 ; nc = not done yet
mov cl,visible ; get moveto or drawto variable
call tekdraw ; move that point
mov visible,1 ; say next time we draw
teklin1:ret
TEKLINE endp
TEKPNT proc near ; FS plot single point
call tekxyc ; parse coordinates
jnc tekpnt1 ; nc = not done yet
mov cl,0 ; do not draw
call tekdraw ; move to the point
mov ax,si ; copy starting point to end point
mov bx,di ; ax,bx,si,di are in PC coordinates
mov cl,1 ; make plot visible
call line ; draw the dot
mov visible,0 ; return to invisibility
tekpnt1:ret
TEKPNT endp
; Decode graphics x,y components. Returns carry set to say have all
; components for a line, else carry clear. Understands 4014 lsb extensions.
; Permits embedded escape sequences.
TEKXYC proc near
cmp al,CR ; Exit drawing on CR,LF,RS,US,FS,CAN
je tekghx ; e = yes, a cr
cmp al,LF ; these terminate line drawing cmds
je tekghx
cmp al,FS ; <FS>
je tekghx
cmp al,RS ; <RS>
je tekghx
cmp al,US ; <US>
je tekghx
cmp al,CAN ; and <CAN>
je tekghx ; BUT ignore other control chars
cmp al,20h ; Control char?
jb tekgh0 ; b = yes, ignore it
cmp al,40h
jb tekgh2 ; 20-3F are HIX or HIY
cmp al,60h ; 40-5F are LOX (causes beam movement)
jb tekgh4 ; 60-7F are LOY
; Extract low-order 5 bits of Y coord
mov ah,tek_loy ; Copy previous LOY to MSB (4014)
mov tek_lsb,ah
and al,1Fh ; LOY is 5 bits
mov tek_loy,al
cmp lastc,loy ; 2nd LOY in a row?
je tekgh1 ; Yes, then LSB is valid
mov tek_lsb,0 ; 1st one, clear LSB
tekgh1: mov lastc,loy ; LOY seen, expect HIX (instead of HIY)
tekgh0: clc ; c clear = not completed yet
ret
tekghx: jmp go2text
; Extract high-order 5 bits (X or Y, depending on lastc)
tekgh2: and ax,1Fh ; Just 5 bits
mov cl,5
shl ax,cl ; Shift over 5 bits
cmp lastc,loy ; was last coordinate a low-y?
je tekgh3 ; e = yes, parse hix
mov tek_hiy,ax ; this byte has HIY
mov lastc,hiy
clc
ret
tekgh3: mov tek_hix,ax ; This byte has HIX
mov lastc,hix
clc
ret
tekgh4: and al,1Fh ; Just 5 bits
mov tek_lox,al
mov lastc,lox
mov ax,tek_hix ; Combine HIX*32
or al,tek_lox ; with LOX
mov bx,tek_hiy ; Same for Y
or bl,tek_loy
stc ; set c to say completed operation
ret
TEKXYC endp
TEKRLIN proc near ; RS relative line drawing
cmp al,' ' ; Pen up command?
jne tekrli1 ; ne = no, try pen down
mov visible,0 ; do invisible movements
jmp short tekrli2 ; do the command
tekrli1:cmp al,'P' ; pen down command?
jne tekrli3 ; ne = no, return to text mode
mov visible,1 ; set visible moves
tekrli2:mov ax,x_coord ; PC x coordinate of pen
mov bx,y_coord ; y coordinate
call pctotek ; get current pen position in Tek coor
mov cl,0 ; invisible, moveto
call tekdraw ; move that point, set oldx and oldy
mov ttstate,offset tekinc ; next get incremental movement cmds
ret
tekrli3:mov visible,0 ; bad char, reset visibility
push prestate
pop ttstate ; restore previous state
jmp tektt5 ; deal with the break char
TEKRLIN endp
; interpret RS inc plot command byte
TEKINC proc near ; get movement character and do cmd
cmp al,'A' ; move right?
jne tekinc1 ; ne = no
inc oldx ; adjust beam position
jmp short tekinc9
tekinc1:cmp al,'E' ; move right and up?
jne tekinc2 ; ne = no
inc oldx
inc oldy
jmp short tekinc9
tekinc2:cmp al,'D' ; move up?
jne tekinc3 ; ne = no
inc oldy
jmp short tekinc9
tekinc3:cmp al,'F' ; move left and up?
jne tekinc4 ; ne = no
dec oldx
inc oldy
jmp short tekinc9
tekinc4:cmp al,'B' ; move left?
jne tekinc5 ; ne = no
dec oldx
jmp short tekinc9
tekinc5:cmp al,'J' ; move left and down?
jne tekinc6 ; ne = no
dec oldx
dec oldy
jmp short tekinc9
tekinc6:cmp al,'H' ; move down?
jne tekinc7 ; ne = no
dec oldy
jmp short tekinc9
tekinc7:cmp al,'I' ; move right and down?
jne tekincb ; ne = no, bad command
inc oldx
dec oldy
tekinc9:cmp oldx,0 ; too far left?
jge tekinc10 ; ge = no
mov oldx,0 ; else stop at the left margin
tekinc10:cmp oldx,maxtekx-1 ; too far left?
jle tekinc11 ; le = no
mov oldx,maxtekx-1 ; else stop that the left margin
tekinc11:cmp oldy,maxteky-1 ; above the top?
jle tekinc12 ; le = no
mov oldy,maxteky-1 ; else stop at the top
tekinc12:cmp oldy,0 ; below the bottom?
jge tekinc13 ; ge = no
mov oldy,0 ; else stop at the bottom
tekinc13:mov ax,oldx ; ax is vector x end point
mov bx,oldy ; bx is vector y end point
mov cl,visible
call tekdraw ; move/draw to that point
ret
tekincb:push prestate ; bad character, exit inc plot mode
pop ttstate ; new state is previous state
mov visible,0
jmp tektt5 ; reparse the bad char
TEKINC endp
; Routine to trigger the crosshairs, wait for a key to be struck, and send
; the typed char (if printable ascii) plus four Tek encoded x,y position
; coordinates and then a carriage return.
; ax, cx, xcross, ycross operate in PC coordinates.
CROSHAIR PROC NEAR
push linepat ; save line drawing pattern
mov linepat,0ffffh ; reset line type to solid
mov ax,xmax ; right margin minus 7 dots
add ax,7
mov temp,ax ; right margin dot
crosha1:call crosdraw ; draw the cross-hairs
call iseof ; is stdin at EOF?
jc crosha2 ; c = yes, exit this mode now
mov ah,coninq ; DOS, quiet read char
int dos
push ax ; save char for later
call crosdraw ; erase cross hairs
pop ax
or al,al ; ascii or scan code returned
jnz arrow5 ; nz = ascii char returned
call iseof ; is stdin at EOF?
jc crosha2 ; c = yes, exit this mode now
mov ah,coninq ; read scan code
int dos
cmp al,0 ; Control-Break?
jne crosha3 ; ne = no, something else
crosha2:pop linepat ; restore line pattern
ret ; exit crosshairs mode
crosha3:cmp al,homscn ; is it 'home'?
jne arrow1 ; ne = no, try other keys
mov ax,temp ; right margin
shr ax,1 ; central position
mov xcross,ax ; save PC coord for crosshair
mov ax,ybot ; last scan line
shr ax,1
mov ycross,ax ; this is the center of the screen
jmp crosha1 ; home the crosshairs
arrow1: cmp al,lftarr ; left arrow?
jne arrow2 ; ne = no
mov cx,-1 ; left shift
jmp short xkeys
arrow2: cmp al,rgtarr ; right arrow?
jne arrow3 ; ne = no
mov cx,1 ; right shift
jmp short xkeys
arrow3: cmp al,uparr ; up arrow?
jne arrow4 ; ne = no
mov cx,-1 ; up shift
jmp short vertkey
arrow4: cmp al,dnarr ; down arrow?
jne arrow7 ; ne = no, ignore it
mov cx,1 ; down shift
jmp short vertkey
arrow7: cmp al,shuparr ; shifted up arrow?
jne arrow8 ; ne = no
mov cx,-10 ; big up shift
jmp short vertkey
arrow8: cmp al,shdnarr ; shifted down arrow?
jne badkey ; ne = no, send this key as is
mov cx,10 ; big down shift
jmp short vertkey
badkey: call beep ; tell user we don't understand
jmp crosha1 ; keep going
; Shifted keys yield ascii keycodes
arrow5: cmp al,'C' and 1fh ; Control-C?
je crosha2 ; e = yes, exit crosshairs mode now
cmp al,shlftarr ; shifted left arrow?
jne arrow6 ; ne = no
mov cx,-10 ; big left shift
jmp short xkeys
arrow6: cmp al,shrgtarr ; shifted right arrow?
jne charkey ; ne = no
mov cx,10 ; big right shift
jmp short xkeys
xkeys: add cx,xcross ; add increment
jns noxc ; gone too far negative?
mov cx,0 ; yes - then make it 0
noxc: cmp cx,temp ; too far right?
jb xdraw9 ; b = no
mov cx,temp ; yes - then make it the right
xdraw9: mov xcross,cx ; new x value for cross hairs
jmp crosha1 ; and redraw
vertkey:add cx,ycross ; adjust cx
jns noyc ; gone negative?
mov cx,0 ; yes then make 0
noyc: cmp cx,ybot ; too high?
jb yok
mov cx,ybot ; make it maximum
yok: mov ycross,cx ; save new y crosshair
jmp crosha1 ; and redraw
charkey:call clrbuf ; purge received data to date
call outmodem ; send the break character
mov ax,xcross ; set beam to xcross,ycross
mov bx,ycross ; must convert to Tek coordinates
call pctotek ; scale from PC screen coord to Tek
push ax ; save around drawing
push bx
mov cx,0 ; just a move
call tekdraw ; moveto ax,bx in Tek coord
pop bx ; recover Tek y
pop ax ; recover Tek x
call sendpos ; send position report to host
pop linepat ; recover current line drawing pattern
mov ttstate,offset tektxt ; Go to TEKTXT next time
mov lastc,0 ; clear last drawing coordinate flag
or status,txtmode ; set text mode in status byte
ret
CROSHAIR ENDP
; CROSDRAW draws cross-hairs by XORing cross with picture.
; xcross and ycross are in PC coordinates.
CROSDRAW PROC NEAR
mov si,xcross ; move to (xcross, ycross-10)
mov di,ycross
sub di,10 ; half the size of the cross
jns crosd1 ; no sign bit means ok
mov di,0 ; else limit to start of screen
crosd1: mov ax,si ; next, draw to (xcross, ycross+10)
mov bx,ycross ; make bottom stroke
add bx,10
cmp bx,ybot ; too large?
jbe crosd2 ; be = no
mov bx,ybot ; vertical line to (xcross,ybot)
crosd2: mov cx,0ffh ; invert pixels
call line ; and draw vertical
sub si,12 ; move to (xcross-12, ycross)
jns crosd3 ; no sign means ok
mov si,0 ; else limit to start of line
crosd3: mov di,ycross
mov bx,di
mov ax,xcross ; draw to (xcross+12, ycross)
add ax,12
cmp ax,temp ; temp is right margin, too large?
jbe crosd4 ; be = no, ok
mov ax,temp ; max x value
crosd4: mov cx,0ffh ; set XOR code
call line ; draw to (xcross+12, ycross)
ret
CROSDRAW ENDP
; SENDPOS sends position of cross-hairs to the host.
; ax has Tek X and bx has Tek Y coord of center of crosshair
SENDPOS PROC NEAR
push bx ; preserve register
call sendxy ; send x coord
pop ax
call sendxy ; send y coord
mov al,cr ; follow up with cr
call outmodem
ret
SENDPOS ENDP
; SENDXY sends value of ax as Tek encoded bytes
; ax is in Tek coordinates
SENDXY PROC NEAR
shl ax,1
shl ax,1 ; move all but lower 5 bits to ah
shl ax,1
shr al,1
shr al,1 ; move low five bits to low 5 bits
shr al,1
or ah,20h ; make it a printing char as per TEK
xchg al,ah ; send high 5 bits first
call outmodem
xchg al,ah ; then low five bits
or al,20h
call outmodem
xchg ah,al ; al is first sent byte
ret
SENDXY ENDP
SENDID PROC NEAR ; Pretend VT100 with graphics option
mov bx,IDSEQ ; Get addr of string
sndid1: mov al,[bx] ; Get char from sequence
cmp al,0 ; End of sequence?
jz sndid0 ; Yes, return
call OUTMODEM ; Send it out the port
inc bx
jmp sndid1
sndid0: ret
SENDID ENDP
; SENDSTAT - send status and cursor position to host
SENDSTAT PROC NEAR
mov al,STATUS ; get tek status
or al,20h ; make it printable
call OUTMODEM ; and send it
mov ax,oldx ; now send x coordinate (oldx is Tek)
call SENDXY
mov ax,oldy ; and y coordinate (oldy is Tek coord)
call SENDXY
mov al,cr ; end with a cr
call OUTMODEM
ret
SENDSTAT ENDP
; routine to send al to the modem port
OUTMODEM PROC NEAR
push ax
mov ah,al
call outchr ; outchr reads from ah
nop ; ignore errors
nop
nop
pop ax
ret
OUTMODEM ENDP
; Convert X and Y from PC coordinates to Tek coordinates. AX = X, BX = Y
; for both input and output.
pctotek proc near
mul xdiv ; scale from PC screen coord to Tek
div xmult
xchg bx,ax ; save Tek x coord in bx
neg ax ; y axis. Turn upside down for Tek
add ax,ybot
mul ydiv ; scale y from PC screen coord to Tek
div ymult
xchg ax,bx ; ax has X, bx has Y in Tek coords
ret
pctotek endp
; Routine to output character in AL to the screen.
OUTSCRN PROC NEAR ; Output one character to the screen
cmp bypass,0 ; GIN mode bypass off?
je outscp ; e = yes
ret ; else ignore characters
outscp: ; Set Translation Input filter
cmp rxtable+256,0 ; translation turned off?
je outsct ; e = yes, no translation
push bx
mov bx,offset rxtable ; address of translate table
xlatb ; new char is in al
and al,7fh ; retain only lower seven bits
pop bx
outsct: mov ccode,1 ; normal text [jan]
mov si,ybot ; get last scan line
inc si ; number of scan lines
sub si,y_coord ; minus where char bottom needs to go
jnc outscc ; nc = enough space for char
; took out more stuff [jan]
mov y_coord,0 ; back to top of screen [jan]
outscc: push ax
mov ax,xmax
cmp x_coord,ax ; beyond right margin?
jbe outsc3 ; be = no
mov al,cr ; else simulate cr/lf
call putc ; before displaying current char
mov al,lf
call putc
outsc3: pop ax
call putc ; routine to draw characters
ret
OUTSCRN ENDP
; TEKCLS routine to clear the screen.
; Entry point tekcls1 clears screen without resetting current point.
TEKCLS PROC NEAR
cmp tekflg,0 ; Tek sub mode active yet?
jne tekcls0 ; ne = yes
ret ; else ignore this call
tekcls0:mov x_coord,0 ; starting text coordinates
mov y_coord,8
mov oldx,0 ; assumed cursor starting location
mov oldy,maxteky ; top right corner (Tek coord)
mov scalex,0 ; clear last plotted point (PC coord)
mov scaley,0
mov lastc,0 ; last parsed x,y coordinate
mov visible,0 ; make lines invisible
mov linepat,0ffffh ; reset line pattern to solid
mov ccode,1 ; reset to ordinary writing
mov bypass,0 ; clear bypass condition
mov ttstate,offset tektxt ; do displayable text
push ax
mov ax,xmax ; right margin minus 7 dots
add ax,7 ; right most dot
shr ax,1 ; central position
mov xcross,ax ; save PC coord for crosshair
mov ax,ybot ; last scan line
shr ax,1
mov ycross,ax ; this is the center of the screen
pop ax
tekcls1:push ax ; save registers
push cx
call cmblnk ; clear the screen
tekcls7:mov si,0 ; starting x (in case screen is
mov di,0 ; starting y cleared by user)
pop cx
pop ax
ret
TEKCLS ENDP
; Routine to draw a line on the screen, using TEKTRONIX coordinates.
; X coordinate in AX, 0=left edge of screen, 1023=right edge of screen.
; Y coordinate in BX, 0=bottom of screen, 779=top of screen.
; CL=0 - invisible move, CL=1 - draw a line, CL=0FFh - invert pixels on line
TEKDRAW PROC NEAR
mov si,scalex ; get old x already scaled
mov di,scaley ; get old y already scaled
call scale ; scale new end point to PC coords
cmp cl,0 ; invisible drawing?
je moveto ; z = just move, skip draw part
call LINE ; draw the line
moveto: mov x_coord,ax ; update text coordinates to match
mov y_coord,bx ; last drawn point
ret
TEKDRAW ENDP
; Scale TEKTRONIX coordinates to the currently defined screen coordinates
; AX holds X axis, BX holds Y axis. Both are changed from Tektronix coord
; to PC coordinates by this procedure.
SCALE PROC NEAR
push dx
push si
mov oldx,ax ; save current Tek x for next draw
mov oldy,bx ; save current Tek y for next draw
mul xmult ; scale x-coord
mov si,xdiv ; get the divisor
shr si,1 ; halve it
add ax,si ; add in - to round to nearest integer
adc dx,0
div xdiv
cmp oldx,maxtekx-1 ;at right of screen? [jan]
jne scale2 ;ne means not at edge [jan]
mov ax,xmax ;right of display on PC [jan]
add ax,7 ;[jan]
scale2: push ax
mov ax,bx
mul ymult ; scale y-coord
mov si,ydiv ; get divisor
shr si,1 ; halve it
add ax,si ; add in - to round to nearest integer
adc dx,0
div ydiv
mov bx,ybot
sub bx,ax ; Put new Y in right reg
jns scale3 ; ns = not too far
mov bx,0
scale3: pop ax ; Put new X in right reg
mov scalex,ax ; save scaled values
mov scaley,bx
pop si
pop dx
ret
SCALE ENDP
; LINE Subroutine to plot a line with endpoints in AX,BX and SI,DI.
; fast line drawing routine for the IBM PC
;
; Registers at CALL
; -----------------
; SI=Start X coord, all in PC coordinates
; DI=Start Y coord
; AX=End X coord
; BX=End Y coord
; CL=Color code: 1=draw foreground, 0=draw background, 0ffh=invert
; BP= line drawing pattern (is changed here by rotation)
; registers are all unchanged
LINE PROC NEAR
push ax
push bx
push cx
push dx
push si
push di
push es
mov bp,linepat ; store active line pattern word in BP
mov ccode,cl ; save color code in ccode for use by plot()
; first get coord to achieve increasing x; deltax >= 0
sub ax,si ; deltax = x2 - x1
jge line1 ; ge = going to the right, as desired
neg ax ; make deltax non-negative
sub si,ax ; swap the x coordinates
xchg bx,di ; swap the y coordinates too
; second, compute deltay. ax = deltax, si = x1
line1: sub bx,di ; deltay = y2 - y1
call psetup ; setup display adapter for plotting
; and setup es:di to screen memory
; Choose algorithm based on |deltay| < |deltax| (use shallow) else steep.
; We arrange matters such that both deltas are non-negative.
cmp bx,0 ; deltay
jge line2 ; ge = non-negative
neg linelen
neg bx ; make non-negative
line2: cmp bx,ax ; |deltay| versus |deltax|
jbe shallow ; be = do shallow algorithm
jmp steep ; else do steep algorithm
; shallow algorithm, move along x, di=y1, bx=deltay, si=x1, ax=deltax
shallow:add bx,bx ; bx = 2*deltay
mov cx,ax ; cx = number of steps (deltax here)
inc cx ; loop dec's cx before testing
mov dx,bx ; dx holds error
sub dx,ax ; error = 2*deltay - deltax
add ax,ax ; ax = 2*|deltax|
shal1: call plotptr ; Plot(x,y)
cmp dx,0
jle shal2 ; le = error <= 0
call pincy ; increment y by one scan line
sub dx,ax ; error = error - 2*deltax
shal2: add dx,bx ; error = error + 2*deltay
inc si ; x = next dot right
loop shal1
shal3: jmp short plotex
; steep algorithm, move along y, di=y1, bx=deltay, si=x1, ax=deltax
steep: add ax,ax ; ax = 2*deltax
mov dx,ax ; dx holds error
sub dx,bx ; error = 2*deltax(bx) - deltay (bx)
mov cx,bx ; cx = number of steps (deltay here)
inc cx ; loop dec's cx before testing
add bx,bx ; bx = 2*|deltay|
stee1: call plotptr ; Plot(x,y) x = ax, y = di
cmp dx,0
jle stee2 ; le error <= 0
inc si ; x = next dot right
sub dx,bx ; error = error - 2*deltay
stee2: add dx,ax ; error = error + 2*deltax
call pincy ; increment y
loop stee1
stee3:;;;jmp plotex
plotex: mov ccode,1 ; reset to do foreground coloring
pop es
pop di
pop si
pop dx ; restore the world
pop cx
pop bx
pop ax
ret
LINE ENDP
;;;;;;;; CGA plot support routines
; The CGA graphics memory mapping in mode 6 (640 by 200) is 8 dots per byte,
; left most dot in the high bit, 80 bytes per scan line, scan line segments
; alternating between 0b800h (even lines 0, 2, ...) and 0ba00h (odd lines).
psetupc proc near ; CGA setup for plotting
push ax
push cx
mov ax,linebytes
mov linelen,ax ; 40 bytes per scan line
mov cx,segscn ; small grid scn [jan]
mov es,cx
mov cx,di ; save copy of di, start y line
; compute starting point in regen buff
mov ax,linebytes ; bytes per line [jan]
mul di
mov di,ax ; di = di * linebytes
pop cx
pop ax
ret
psetupc endp
pincyc proc near ; CGA inc y
add di,linelen ; add a line
ret
pincyc endp
pltcga proc near ; CGA plot(x,y). x is in si, y is in di
push bx ; used for HGA plot also.
push si
push di
rol bp,1 ; rotate line pattern
jnc pltcg3 ; nc = no bit to be plotted
mov bx,si ; want si/8 for bytes along line
shr si,1
shr si,1
shr si,1
xor si,1 ;bytes in hl order on GRiD [jan]
add di,si ; starting point in regen buffer
and bx,0007h ; leave lower 3 bits for bit in byte
; di = offset in regen buffer
mov bh,masktab[bx] ; 0-7 into bit mask in byte. x position
mov bl,ccode ; get line type code
cmp bl,1 ; draw the bit?
jne pltcg1 ; ne = no
or es:[di],bh ; drawn
jmp short pltcg3
pltcg1: cmp bl,0 ; draw in background (erase)?
jne pltcg2 ; ne = no
not bh
and es:[di],bh ; erase the dots
jmp short pltcg3
pltcg2: xor es:[di],bh ; xor in this color
pltcg3: pop di
pop si
pop bx
ret
pltcga endp
; GPUTC - a routine to send text characters from font to true graphics boards
; such as EGA, Hercules or CGA. Char is in al. Drawing routine ptr is gcplot.
gputc proc near
cmp al,' ' ; control character?
jae gputc1 ; ae = no, display the char
jmp putctrl ; else handle controls at putctrl
gputc1: push ax ; first save some registers
push bx
push cx
push es
push di
mov bl,al ; now BL has char to be displayed
and bl,7fh ; no high bits allowed here
; set board mode
mov di,y_coord ; get current y coord (char bottom)
sub di,8 ; start 8 lines higher
jnc gputc2 ; nc = ok
mov di,0 ; move up to first line
mov y_coord,8 ; and reset scan line indicator
gputc2: call psetup ; enter with di=line number, sets es:di to
; start of line in display buf and
; sets byte-wide plot mode
mov ax,x_coord ; compute regen buffer byte
shr ax,1 ; want x_coord/8 for bytes along line
shr ax,1
shr ax,1
xor ax,1 ;bytes in hl order on grid [jan]
add di,ax ; byte in regen buffer
xor bh,bh
sub bx,32 ; characters in font start at 32
shl bx,1
shl bx,1 ; 8 bytes per char - hence * 8
shl bx,1
mov cx,8 ; 8 bytes (scan lines) to transfer
call gcplot ; call character plot routine
call incx ; move to next char position
pop di
pop es
pop cx
pop bx
pop ax
ret
gputc endp
putctrl proc near ; CONTROL CHARS = cursor movement
push ax ; save character
cmp al,FF ; formfeed?
jne putct0 ; ne = no
call TEKCLS ; FF clears the screen
jmp putctx
putct0: cmp al,BS ; BS? sends (logical) cursor back one
jne putct2 ; ne = no, try next
mov ax,x_coord
sub ax,8 ; so delete 8 dots (move left)
jns putct1 ; ns = non-negative
mov ax,0 ; but not less than 0
putct1: mov x_coord,ax ; and replace x coordinate
mov al,' ' ; send a space
call putc
sub x_coord,8 ; restore cursor
jmp putctx
putct2: cmp al,tab ; tabs move forward one char position
jne putct4 ; ne = not a tab
call incx ; let incx move cursor right one col
jmp putctx
putct3: mov x_coord,ax
jmp putctx
putct4: cmp al,cr ; <CR> means go to beginning of line
jne putct5
mov x_coord,0 ; zero the x coordinate
jmp putctx
putct5: cmp al,lf ; <LF> means go down 8 pixels (1 line)
jne putct7 ; ne = not LF
add y_coord,8 ; border managed by outscrn and incx
jmp putctx
putct7: cmp al,vt ; <VT> move up screen 1 line (8 pixels)
jne putctx
sub y_coord,8 ; subtract one line (8 pixels)
jnc putctx ; nc = space left
mov y_coord,8 ; else set to top of screen
putctx: pop ax
ret
putctrl endp
incx proc near ; move the logical cursor right
mov ax,x_coord ; shift the (logical) cursor right
add ax,8 ; one character cell
mov x_coord,ax
cmp ax,xmax ; at end of the line?
jbe incx1 ; b = no
mov x_coord,0 ; wrap to next line
add y_coord,8 ; next row
mov ax,ybot ; last scan line
cmp ax,y_coord ; below bottom line?
jge incx1 ; ge = no
mov y_coord,ax ; set to bottom row
mov al,lf ; simulate a line feed operation
call outscrn ; invoke More message
incx1: ret
incx endp
; General Character plot routine. Enter with bx pointing at font array for
; char, cx = number of bytes in char font, es:di = screen memory.
; Worker for gputc.
gcgen proc near
gcgen1: mov al,font[bx] ; Non-EGA systems: get bits from font
cmp ccode,1 ; write in foreground?
je gcgen2 ; e = yes
xor es:[di],al ; background or xor (same)
jmp short gcgen3
;;;; mov es:[di],al ; write desired pattern (no overwrite)
gcgen2: OR es:[di],al ; write desired pattern (no overwrite)
gcgen3: inc bx ; point to next byte of char pattern
call pincy ; next scan line (linelen is preset)
loop gcgen1 ; and repeat until complete
ret
gcgen endp
teksave proc near ; saves graphics screen
; mimic procedure in msxgri.asm [jan]
ret
teksave endp
tekrest proc near ; saves graphics screen of page 0 in page 1
push si
push di
; need to mimic the procedure in msxgri.asm for restoring a screen
tekresx:pop di
pop si
ret
tekrest endp
code ends
end