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 . 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 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 to - 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 ; je tekghx cmp al,RS ; je tekghx cmp al,US ; je tekghx cmp al,CAN ; and 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 ; means go to beginning of line jne putct5 mov x_coord,0 ; zero the x coordinate jmp putctx putct5: cmp al,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 ; 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