home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
archives
/
msr313src.zip
/
msgap3.asm
< prev
next >
Wrap
Assembly Source File
|
1988-08-16
|
76KB
|
1,545 lines
Name msgap3
; File MSGAP3.ASM
; Tektronix emulator for use with MS Kermit/IBM.
; Edit history:
; Last edit 18 March 1988
; 18 Mar 1988 V2.30 adapted for the NEC APCIII -- RFGoeke
; The NEC version uses only a single VRAM page which cannot be saved
; (because a mode select call clears the VRAM!) in your choice of green.
; The gbcol variable is used to indicate normal (0) or reverse (1) video.
; For readability, a linefeed was set to 10 pixels.
; NEC also does not respond well to DOS keyboard calls; use BIOS
; 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
; Converted to IBM PCs by Brian Holley, Cambridge Univ.
; 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-Z turns on the crosshairs (not on 4006 or 4025)
; 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.
; 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.
; =============================================================================
;
; - ctrl-g (BEL) from line gives beep in tek mode
; - characters better placed in relation to current beam position
; in EGA and Hercules modes
; characters OR-ed into place rather than overwriting
; - add SET TERMINAL GRAPHICS NONE - this ignores the start-up ESC-FF
; for Tektronix
; - add MonoEGA mode for monochrome graphics on an EGA
;
; version 2.29/t3
; changes - stop control characters from echoing to screen in TEKEMU
; - show version on name in MSSDEF.H
; version 2.29b
; changes with this version: - faster line drawing, using direct write to
; memory rather than BIOS calls
; - support for Hercules, Olivetti, EGA
; - minor bug fixes
; adapted to IBM PC June 1987 by Brian Holley,
; Faculty of Economics and Politics
; University of Cambridge, England
; Email: BJH6@UK.AC.CAM.PHX
public tekemu,tekini,tekend ; Terminal emulation routines
public tekcls, tekesc, tekflg ; used by msz file
include mssdef.h
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
screen equ 19h ; bios screen call -- NEC
kbint equ 18H ; bios keyboard call -- NEC
uparr equ 39h ; DOS scan codes for arrow keys -- NEC
dnarr equ 3Ch ; these are also the "extended" codes
lftarr equ 3Ah
rgtarr equ 3Bh
homscn equ 3Dh ; DOS home screen scan code -- NEC
shuparr equ 0B4h ; "extended" codes for CTRL-Arrows
shdnarr equ 0B7h
shlftarr equ 0B5h
shrgtarr equ 0B6h
; Graph_mode for different systems:
; NEC resolution = Olivetti (640 x 400)
; Though we set mode for color, BIOS will go to B&W if adaptor board absent
olivetti equ 9 ; Olivetti's Hi-res - 50 lines text
segcga equ 0A800h ; CGA, AT&T/Olivetti -- NEC !!!
hiy equ 1 ; codes for Tek graphics components
loy equ 2
hix equ 4
lox equ 3
att_low_mask equ 1fH ; Various NEC attribute-related equates
att_overline equ 01H ; this is all NEC version stuff RFG
att_blink equ 02H
att_rev_video equ 04H
att_underline equ 08H
att_intensity equ 04H ; same as reverse video
col_high_mask equ 0E0H
nec_black equ 00H ; This table gives colors RFG
nec_blue equ 20H ; (only bits 8,7,6 count)
nec_red equ 40H
nec_magenta equ 60H
nec_green equ 80H
nec_cyan equ 0A0H
nec_yellow equ 0C0H
nec_white equ 0E0H
datas segment public 'datas'
extrn flags:byte, portval:word, rxtable:byte, vtemu:byte
; extrn tv_mode:byte ; NEC omits
scrsave dw ? ; segment addr of memory for screen save (NEC)
xmult dw ? ; scaling factor for x is
xdiv dw ? ; xmult/xdiv
ymult dw ? ; scaling factor for y is
ydiv dw ? ; ymult/ydiv
xmax dw ? ;
ybot dw ? ;
; required for Hercules screen handling
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 'NEC_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
; local variables for LINE plotting routine
graph_mode db 0 ; graphics video mode, default is none
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 (NEC omit)
gbcol db 0 ; graphics background color
moremsg db ' More >'
mormsglen equ $-moremsg ; length of message
ccode db 0 ; temp for holding plot color code
linelen dw 0 ; offset increment between scan lines
putc dw ? ; ptr to plot a character routine
psetup dw ? ; ptr to plot setup routine
pfin dw ? ; ptr to plot cleanup routine
pincy dw ? ; ptr to inc y routine
plotptr dw ? ; ptr to dot plot routine
segscn dw ? ; actual screen segment to use
; ANSI Escape sequence to turn off Media Copy (Print Controller Off)
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
repbuf db 6 dup (0) ; crosshairs report buf
repcnt db 0 ; number of untouched chars in repbuf
temp dw 0
; 8*8 font for Hercules, CGA, and EGA TEK mode
; - 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)
datas ends
code segment public 'code'
extrn outchr:near, beep:near, scrseg:near, cmblnk:near
extrn clrmod:near, savescr:near, cptchr:near, pcwait:near
extrn restscr:near, getflgs:near, clrbuf:near, vtans52:near
assume cs:code, ds:datas, es:nothing
; Initialise TEK mode by setting high resolution screen, etc
;The Olivetti has (639,399) as the coordinate of the lower-right corner.
;Calculate endpoint X=(5/8)*(HIX*32+LOX), Y=399-(20/39)*(HIY*32+LOY)
tekini PROC NEAR
push ax ; do presence tests. [jrd]
push bx
push cx
push dx
push si
push di
push es
; NEC handles flow control in hardware; see SERINIT in msxap3
; NEC uses green graphic plane (only)
mov gbcol,0 ; NEC: this is normal video
push si ; NEC
mov ah,15 ; get current screen mode
int screen
pop si ; NEC
cmp al,3 ; in a mono/color text mode (2/3)?
jbe tekin1 ; be = yes
; cmp al,mono ; mono text mode (7)?
; je tekin1 ; e = yes
cmp tekflg,0 ; are we active as Tek device now?
je tekin1 ; e = no
jmp tekin13 ; yes, don't redo graphics setup
tekin1: mov curmode,al ; save mode here
mov ah,3 ; get cursor position
xor bh,bh ; page 0
int screen
mov cursor,dx ; save position
call savescr ; save text screen
; Presence tests.
tekin2:
mov xmult,5 ; CGA. Scale TEK to PC by 640/1024
mov xdiv,8 ; so that 0-1023 converts to 0-639
mov xmax,640-8 ; x-coord of rightmost character
tekin7:
mov graph_mode,olivetti ; Olivetti
mov gpage,0 ; only page 0 with 640 by 400 mode
mov segscn,segcga ; use cga screen segment (0b800h)
mov psetup,offset psetupn ; plot setup routine for NEC
mov plotptr,offset pltcga ; cga dot plot routine
mov pfin,offset pfinc ; cleanup routine
mov pincy,offset pincym ; inc y routine (NEC is straight)
mov putc,offset gputc ; character display routine
mov ybot,399 ; bottom of screen is y = 399
mov ymult,20 ; Olivetti vertical scale = 400/780
mov ydiv,39 ; same as cga setup
; Set Graphics mode
;tekin13:
tekin14:mov ah,0 ; set screen mode
mov al,graph_mode ; to this screen mode
tekin15:int screen ; Bios Set Mode.
mov ax,100 ; wait 100 millisec
call pcwait ; NEC requires >65 millisec pause here
mov ah,1 ; and kill cursor while we wait
tekin13: mov ch,80h
int screen
tekin16:mov tekflg,1 ; starting Tek sub mode
; cmp inited,0 ; inited yet? NEC didn't save
; 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, for ega coloring
; jmp short tekin20 ; flow control in hardware on NEC
;tekin19:call tekrest ; not saved on NEC
;tekin20:mov ax,flow ; get flow control word
; xchg ah,al ; get xon into al
; cmp al,0 ; able to send xon?
; je tekin21 ; e = no
; call outmodem ; tell host xon
;tekin21:clc ; clear carry for success
; jmp short tekin23
;tekin22:stc ; set carry for failure
tekin23:pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
tekini 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
cmp al,0 ; null char response?
je tekign ; e = yes, ignore the character
; check for echo of crosshair report
cmp repcnt,0 ; any chars need matching in report?
je tektt5a ; e = no
push bx ; yes
mov bx,6 ; number of bytes in crosshairs rpt
sub bl,repcnt ; number of chars needing matching
cmp al,repbuf[bx] ; received same as current rpt char?
pop bx
jne tektt5a ; ne = mismatch, stop echo test
dec repcnt ; say one more matched
clc ; absorb without comment
ret ; stay in this state
tektt5a:mov repcnt,0 ; clear report count
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
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
mov ttstate,offset tektxt ; back to text mode
test flags.vtflg,tttek ; main Tek emulator?
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: ; NEC can't save (VRAM is destroyed by mode switch)
call tekcls ; clear screen to avoid flash
teknd1: mov ah,0 ; set video mode
mov al,curmode ; restore previous screen mode
int screen ; revert to text screen
mov ax,100 ; wait 100 millisec
call pcwait ; NEC requires >65 millisec pause here
call restscr ; restore text screen
mov dx,cursor ; saved cursor position
mov bh,0 ; page 0
mov ah,2 ; set cursor
int screen
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 ; are we a full Tek terminal now?
jne tkscn2 ; ne = no, a submode
call vtans52 ; toggle terminal type, in msyibm
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 printer
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>
tektx1: cmp al,CR ; ^M Carriage return?
je tektx7 ; e = yes
tektx2: cmp al,LF ; ^J LineFeed?
je tektx7 ; e = yes
tektx3: cmp al,FF ; ^L Formfeed?
jne tektx4 ; ne = no
call tekcls ; clear the screen
jmp short tektx8
tektx4: cmp al,VT ; ^K vertical tab?
je tektx7
cmp al,bell ; ^G bell on line?
jne tektx5 ; ne = no
call beep
jmp short tektx8
tektx5: cmp al,Tab ; Tab?
jne tektx6 ; ne = no
mov al,' ' ; make it a space
tektx6: cmp al,BS ; ^H backspace?
je tektx7 ; e = yes
cmp al,' ' ; control char?
jb tektx8 ; b = yes, ignore it
tektx7: call OUTSCRN ; output character to the screen
tektx8: ret
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 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
; cmp graph_mode,mono ; Monochrome text mode?
; je tekesc3a ; e = yes, no crosshairs in text mode
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
call SENDSTAT ; send status
jmp tekescx
tekesc5:cmp al,accent ; accent grave, line pattern series?
jb tekescx ; b = no
cmp al,65h ; lowercase e?
ja tekescx ; a = beyond line pattern series
push bx
mov bl,al
sub bl,accent ; remove bias
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
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 go2text ; e = yes, a cr
cmp al,LF ; these terminate line drawing cmds
je go2text
cmp al,FS ; <FS>
je go2text
cmp al,RS ; <RS>
je go2text
cmp al,US ; <US>
je go2text
cmp al,CAN ; and <CAN>
je go2text ; 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
; 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, by, xcross, ycross operate in PC coordinates.
; NEC mods to use BIOS key fetch and key translations; since shift-arrow
; is not a unique code, use CTRL-arrow instead
CROSHAIR PROC NEAR
push linepat ; save line drawing pattern
mov linepat,0ffffh ; reset line type to solid
crosha0:mov ax,xmax ; right margin minus 7 dots
add ax,7
mov temp,ax ; right margin 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
crosha1:call crosdraw ; draw the cross-hairs
; mov ah,coninq ; DOS, quiet read char
; int dos
mov ah,0 ; NEC call, returns
int kbint ; ah = scan code, al = ASCII
; if al = 0, ah = "extended code"
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
; 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
cmp al,0
je crosha3 ; e = extended code keys
cmp al,3 ; Control-C?
jne charkey
pop linepat ; restore line pattern
ret ; exit crosshairs mode
charkey:call clrbuf ; purge received data to date
mov repcnt,6 ; set length of report string
mov repbuf,al ; store first report character
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
ret
crosha3:
xchg ah,al
cmp al,homscn ; is it 'home'?
je crosha0 ; e = yes
jmp short arrow1 ; else try the arrow keys
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 arrow5 ; ne = no, ignore it
mov cx,1 ; down shift
jmp short vertkey
arrow5:
cmp al,shlftarr ; shifted left arrow?
jne arrow6 ; ne = no
mov cx,-64 ; big left shift
jmp short xkeys
arrow6: cmp al,shrgtarr ; shifted right arrow?
jne arrow7 ; ne = no
mov cx,64 ; big right shift
jmp short xkeys
arrow7: cmp al,shuparr ; shifted up arrow?
jne arrow8 ; ne = no
mov cx,-32 ; big up shift
jmp short vertkey
arrow8: cmp al,shdnarr ; shifted down arrow?
jne badkey
mov cx,32 ; big down shift
jmp short vertkey
badkey: call beep ; tell user we don't understand
jmp crosha1 ; keep going
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
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-12)
mov di,ycross
sub di,12 ; 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+12)
mov bx,ycross ; make bottom stroke
add bx,12
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
mov word ptr repbuf+1,ax ; first word
pop ax
call sendxy ; send y coord
mov word ptr repbuf+3,ax ; second word
mov al,cr ; follow up with cr
mov repbuf+5,al ; last report character
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
; 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 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
; else give "More >" message
push ax ; save current char
mov ax,mormsglen ; characters in More message
shl ax,1
shl ax,1
shl ax,1 ; times 8 bits/character
neg ax ; (note: leave last char cell empty)
add ax,xmax ; right justify
mov x_coord,ax ; set starting x dot
mov ax,ybot
mov y_coord,ax ; set starting y line
; mov ah,gfcol ; get screen coloring
; mov al,gbcol
; push ax ; save it
xchg ah,al ; interchange colors for message
; mov gfcol,ah
mov gbcol,1 ; NEC: set reverse video
mov si,offset moremsg ; give More message
push cx
mov cx,mormsglen
outsclf:cld
lodsb ; read a byte from string
call putc ; display the string
loop outsclf ; repeat for all string chars
pop cx
; pop ax ; restore normal video
; mov gfcol,ah
mov gbcol,0 ; NEC: set nromal video
mov ah,coninq ; read keyboad via DOS
int dos ; wait for keystroke
or al,al ; scan code being returned?
jne outscl3 ; ne = no
mov ah,coninq ; clear away scan code too
int dos
outscl3:call tekcls ; clear the screen
pop ax ; recover current character
cmp al,lf ; just a line feed?
jne outscc ; ne = no, display it
ret ; else ignore the line feed
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 ttstate,offset tektxt ; do displayable text
tekcls1:push ax ; save registers
push cx
tekcls2:mov di,0 ; point to start of screen, di=row
call psetup ; setup graphics routine and es:di
mov cx,8000h ; Olivetti, 400 lines times 80 bytes
tekcls3:cld ; clear screen directly of text stuff
mov al,0 ; color is black
rep stosb ; clear the bytes
jmp short tekcls7
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
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 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: call pfin ; cleanup boards after plotting
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
pfinc proc near ; CGA end of plot board cleanup
ret
pfinc 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
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
pincym proc near ; Monochrome inc y
add di,linelen ; includes sign
ret
pincym endp
;;;;;;;;;;;;;;; NEC plot support routines
; In modes 8 and 9 (640 by 400) we have 8 dots per byte,
; left most dot in the high bit, 80 bytes per scan line, scan line segments
; are totally sequential.
psetupn proc near
push ax
mov linelen,80 ; for y going down screen by incy
mov ax,segscn ; base segment of display memory
mov es,ax
mov ax,80
mul di
mov di,ax ; di = di * 80
pop ax
ret
psetupn endp
; GPUTC - a routine to send text characters from font to true graphics boards
; such as EGA, Hercules or CGA. Char is in al.
gputc proc near
cmp al,' ' ; control character?
jae gputc1 ; ae = no, display the char
jmp putctrl ; else handle controls at putctrl
gputc1: push bx ; first save some registers
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
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
gputc4: mov al,font[bx] ; Non-EGA systems: get bits from font
cmp gbcol,0
je gputc5
xor al,0FFh
gputc5: mov es:[di],al ; write desired pattern (no overwrite)
inc bx ; point to next byte of char pattern
call pincy ; inc to next line (linelen is preset)
loop gputc4 ; and repeat 'til complete
gputx: call incx ; move to next char position
pop di
pop es
pop cx
pop bx
ret
gputc endp
putctrl proc near ; CONTROL CHARS = cursor movement
cmp al,FF ; formfeed?
jne putct0 ; ne = no
call TEKCLS ; FF clears the screen
ret
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
ret
putct2: cmp al,tab ; tabs move forward one char position
jne putct4 ; ne = not a tab
mov ax,x_coord
add ax,8 ; so add 8
cmp ax,xmax ; zero if off edge of screen
jbe putct3
mov x_coord,0
mov al,lf
jmp short putct5 ; process our new line feed
putct3: mov x_coord,ax
ret
putct4: cmp al,cr ; <CR> means go to beginning of line
jne putct5
mov x_coord,0 ; zero the x coordinate
ret
putct5: cmp al,lf ; <LF> means go down 8 pixels (1 line)
jne putct7 ; ne = not LF
add y_coord,10 ; NEC version has 2 pixel space
ret
putct7: cmp al,vt ; <VT> move up screen 1 line (8 pixels)
jne putctx
sub y_coord,10 ; NEC uses 10
jnc putctx ; nc = space left
mov y_coord,10 ; NEC uses 10
putctx: 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
code ends
end